diff --git a/.asf.yaml b/.asf.yaml new file mode 100644 index 0000000000..f5a5b4873e --- /dev/null +++ b/.asf.yaml @@ -0,0 +1,39 @@ +# Documentation https://s.apache.org/asfyaml +notifications: + commits: commits@struts.apache.org + # Send all issue emails (new, closed, comments) to issues@ + issues: issues@struts.apache.org + # Send new/closed PR notifications to commits@ + pullrequests_status: notifications@struts.apache.org + # Send individual PR comments/reviews to issues@ + pullrequests_comment: notifications@struts.apache.org + # Link opened PRs with JIRA + jira_options: link label worklog + +github: + description: "Apache Struts is a free, open-source, MVC framework for creating elegant, modern Java web applications" + homepage: https://struts.apache.org/ + del_branch_on_merge: true + protected_branches: + main: + # contexts are the names of checks that must pass. + required_status_checks: + contexts: + - "Build and Test (JDK 17)" + required_pull_request_reviews: + # it does not work because our github teams are private/secret, see INFRA-25666 + require_code_owner_reviews: false + required_approving_review_count: 0 + release/struts-6-7-x: + # contexts are the names of checks that must pass. + required_status_checks: + contexts: + - "Build and Test (JDK 17)" + required_pull_request_reviews: + # it does not work because our github teams are private/secret, see INFRA-25666 + require_code_owner_reviews: false + required_approving_review_count: 0 + autolink_jira: + - WW + dependabot_alerts: true + dependabot_updates: true diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000000..97912ddb4d --- /dev/null +++ b/.gitattributes @@ -0,0 +1,5 @@ +# Set the default behavior, in case people don't have core.autocrlf set. +* text=auto +*.bat eol=crlf +*.cmd eol=crlf +*.sh eol=lf diff --git a/.github/dependabot.yml b/.github/dependabot.yml new file mode 100644 index 0000000000..53b5411943 --- /dev/null +++ b/.github/dependabot.yml @@ -0,0 +1,11 @@ +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "weekly" + - package-ecosystem: "maven" + directory: "/" + schedule: + interval: "weekly" + ignore: [] diff --git a/.github/workflows/codeql.yml b/.github/workflows/codeql.yml new file mode 100644 index 0000000000..623f81eeee --- /dev/null +++ b/.github/workflows/codeql.yml @@ -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. + +name: "CodeQL" + +on: + push: + branches: + - 'main' + - 'release/*' + pull_request: + +permissions: + # Needed to upload the results to code-scanning dashboard. + security-events: write + actions: read + contents: read + # Needed to access OIDC token. + id-token: write + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + permissions: + actions: read + contents: read + security-events: write + strategy: + fail-fast: false + matrix: + language: [ 'java' ] + steps: + - name: Checkout repository + uses: actions/checkout@v4 + - name: Setup Java JDK + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: 'maven' + - name: Initialize CodeQL + uses: github/codeql-action/init@v3.29.0 + with: + languages: ${{ matrix.language }} + - name: Autobuild + uses: github/codeql-action/autobuild@v3.29.0 + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v3.29.0 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/maven.yml b/.github/workflows/maven.yml new file mode 100644 index 0000000000..b977f95855 --- /dev/null +++ b/.github/workflows/maven.yml @@ -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. + +name: Java Maven + +on: + pull_request: + push: + branches: + - 'main' + - 'release/*' + +permissions: read-all + +env: + MAVEN_OPTS: -Xmx2048m -Xms1024m + LANG: en_US.utf8 + +jobs: + build: + name: Build and Test (JDK ${{ matrix.java }})${{ matrix.profile == '-Pjakartaee11' && ' with Jakarta EE 11' || matrix.profile }} + runs-on: ubuntu-latest + strategy: + matrix: + include: + - java: '17' + profile: '' + - java: '21' + profile: '' + - java: '21' + profile: '-Pjakartaee11' + steps: + - name: Checkout code + uses: actions/checkout@v4 + - name: Setup Java ${{ matrix.java }} + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: ${{ matrix.java }} + cache: 'maven' + - name: Maven Verify on Java ${{ matrix.java }}${{ matrix.profile == '-Pjakartaee11' && ' (Jakarta EE 11)' || matrix.profile }} + run: mvn -B -V -DskipAssembly verify ${{ matrix.profile }} --no-transfer-progress diff --git a/.github/workflows/scorecards-analysis.yaml b/.github/workflows/scorecards-analysis.yaml new file mode 100644 index 0000000000..b5570dd3ae --- /dev/null +++ b/.github/workflows/scorecards-analysis.yaml @@ -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. + +name: "Scorecards supply-chain security" + +on: + branch_protection_rule: + schedule: + - cron: "30 1 * * 6" # Weekly on Saturdays + push: + branches: + - "main" + +permissions: read-all + +jobs: + + analysis: + + name: "Scorecards analysis" + runs-on: ubuntu-latest + permissions: + # Needed to upload the results to the code-scanning dashboard. + security-events: write + actions: read + id-token: write # This is required for requesting the JWT + contents: read # This is required for actions/checkout + + steps: + + - name: "Checkout code" + uses: actions/checkout@v4 # 3.1.0 + with: + persist-credentials: false + + - name: "Run analysis" + uses: ossf/scorecard-action@05b42c624433fc40578a4040d5cf5e36ddca8cde # 2.4.2 + with: + results_file: results.sarif + results_format: sarif + # A read-only PAT token, which is sufficient for the action to function. + # The relevant discussion: https://github.com/ossf/scorecard-action/issues/188 + repo_token: ${{ secrets.GITHUB_TOKEN }} + # Publish the results for public repositories to enable scorecard badges. + # For more details: https://github.com/ossf/scorecard-action#publishing-results + publish_results: true + + - name: "Upload artifact" + uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # 4.6.2 + with: + name: SARIF file + path: results.sarif + retention-days: 5 + + - name: "Upload to code-scanning" + uses: github/codeql-action/upload-sarif@be30325fa679497c9a67f006166793cfa1d5840d # 2.22.11 + with: + sarif_file: results.sarif diff --git a/.github/workflows/sonar.yml b/.github/workflows/sonar.yml new file mode 100644 index 0000000000..2d5397e17d --- /dev/null +++ b/.github/workflows/sonar.yml @@ -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. + +name: SonarCloud + +on: + pull_request: + push: + branches: + - 'main' + +permissions: read-all + +env: + MAVEN_OPTS: -Xmx2048m -Xms1024m + LANG: en_US.utf8 + +jobs: + sonarcloud: + name: Scan + runs-on: ubuntu-latest + if: ${{ !github.event.pull_request.base.repo.fork && !github.event.pull_request.head.repo.fork && github.actor != 'dependabot[bot]' }} + steps: + - uses: actions/checkout@v4 + with: + fetch-depth: 0 + - uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 21 + cache: 'maven' + - env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }} + run: ./mvnw -B verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar -Pcoverage -DskipAssembly diff --git a/.gitignore b/.gitignore index 4750576e22..af4e6813cc 100644 --- a/.gitignore +++ b/.gitignore @@ -11,6 +11,9 @@ .metadata/ Servers/ +# Java annotation processor (APT) +.factorypath + #VSCode .vscode @@ -24,41 +27,22 @@ Servers/ .java-version # Maven -core/target -plugins/convention/target -plugins/embeddedjsp/target -plugins/osgi/target -plugins/cdi/target -plugins/spring/target -plugins/jfreechart/target -apps/rest-showcase/target -apps/mailreader/target -apps/portlet/target -apps/blank/target -apps/jboss-blank/target -apps/mailreader/target -apps/portlet/target -apps/showcase/target -apps/target -bundles/admin/target -plugins/config-browser/target -plugins/jasperreports/target -plugins/json/target -plugins/portlet-tiles/target -plugins/portlet/target -plugins/sitegraph/target -plugins/sitemesh/target -plugins/javatemplates/target -bundles/demo/target -plugins/rest/target -plugins/plexus/target -plugins/testng/target -plugins/dwr/target -plugins/gxp/target -plugins/oval/target -plugins/junit/target -plugins/tiles/target -bundles/target -plugins/target -target +target/ +pom.xml.tag +pom.xml.releaseBackup +pom.xml.versionsBackup +pom.xml.next +release.properties +dependency-reduced-pom.xml +buildNumber.properties +.mvn/timing.properties +.mvn/wrapper/maven-wrapper.jar + plugins/testng/test-output +test-output + +# Sonar +/.sonar/ + +# Tidelift CLI scanner +.tidelift diff --git a/.mvn/wrapper/maven-wrapper.properties b/.mvn/wrapper/maven-wrapper.properties new file mode 100644 index 0000000000..d58dfb70ba --- /dev/null +++ b/.mvn/wrapper/maven-wrapper.properties @@ -0,0 +1,19 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +wrapperVersion=3.3.2 +distributionType=only-script +distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.9/apache-maven-3.9.9-bin.zip diff --git a/.travis.yml b/.travis.yml deleted file mode 100644 index 57ba3df4c2..0000000000 --- a/.travis.yml +++ /dev/null @@ -1,9 +0,0 @@ -language: java -sudo: false - -jdk: - - openjdk7 - - oraclejdk8 - -install: true -script: mvn test -DskipAssembly \ No newline at end of file diff --git a/CODEOWNERS b/CODEOWNERS new file mode 100644 index 0000000000..4ddd3b40b4 --- /dev/null +++ b/CODEOWNERS @@ -0,0 +1,2 @@ +# Request PR review from any Apache Struts committer +* @apache/struts-committers diff --git a/Jenkinsfile b/Jenkinsfile new file mode 100644 index 0000000000..1c2028fd23 --- /dev/null +++ b/Jenkinsfile @@ -0,0 +1,215 @@ +#!groovy + +pipeline { + agent none + options { + buildDiscarder logRotator(daysToKeepStr: '14', numToKeepStr: '10') + timeout(80) + disableConcurrentBuilds() + skipStagesAfterUnstable() + quietPeriod(30) + } + triggers { + pollSCM 'H/15 * * * *' + } + stages { + stage('Prepare') { + agent { + label 'ubuntu' + } + stages { + stage('Clean up') { + steps { + cleanWs deleteDirs: true, patterns: [[pattern: '**/target/**', type: 'INCLUDE']] + } + } + } + } + stage('JDK 21') { + agent { + label 'ubuntu' + } + tools { + jdk 'jdk_21_latest' + maven 'maven_3_latest' + } + environment { + MAVEN_OPTS = "-Xmx1024m" + } + stages { + stage('Test') { + steps { + sh './mvnw -B -DskipAssembly verify' + } + post { + always { + junit(testResults: '**/surefire-reports/*.xml', allowEmptyResults: true) + junit(testResults: '**/failsafe-reports/*.xml', allowEmptyResults: true) + } + } + } + } + post { + always { + cleanWs deleteDirs: true, patterns: [[pattern: '**/target/**', type: 'INCLUDE']] + } + } + } + stage('JDK 17') { + agent { + label 'ubuntu' + } + tools { + jdk 'jdk_17_latest' + maven 'maven_3_latest' + } + environment { + MAVEN_OPTS = "-Xmx2048m" + } + stages { + stage('Install') { + steps { + sh './mvnw -B install -DskipTests -DskipAssembly' + } + } + stage('Test') { + steps { + sh './mvnw -B verify -Pcoverage -DskipAssembly' + } + post { + always { + junit(testResults: '**/surefire-reports/*.xml', allowEmptyResults: true) + junit(testResults: '**/failsafe-reports/*.xml', allowEmptyResults: true) + } + } + } + stage('Build Source & JavaDoc') { + when { + anyOf { + branch 'main' + branch 'release/struts-6-7-x' + } + } + steps { + dir("local-snapshots-dir/") { + deleteDir() + } + sh './mvnw -B source:jar javadoc:jar -DskipTests -DskipAssembly' + } + } + stage('Deploy Snapshot') { + when { + anyOf { + branch 'main' + branch 'release/struts-6-7-x' + } + } + steps { + withCredentials([file(credentialsId: 'lukaszlenart-repository-access-token', variable: 'CUSTOM_SETTINGS')]) { + sh './mvnw -s \${CUSTOM_SETTINGS} deploy -DskipTests -DskipAssembly' + } + } + } + stage('Upload nightlies') { + when { + anyOf { + branch 'main' + branch 'release/struts-6-7-x' + } + } + steps { + sh './mvnw -B package -DskipTests' + sshPublisher(publishers: [ + sshPublisherDesc( + configName: 'Nightlies', + transfers: [ + sshTransfer( + remoteDirectory: '/struts/snapshot', + removePrefix: 'assembly/target/assembly/out', + sourceFiles: 'assembly/target/assembly/out/struts-*.zip' + ) + ], + verbose: true + ) + ]) + } + } + } + post { + always { + cleanWs deleteDirs: true, patterns: [[pattern: '**/target/**', type: 'INCLUDE']] + } + } + } + } + post { + // If this build failed, send an email to the list. + failure { + script { + emailext( + to: "notifications@struts.apache.org", + recipientProviders: [[$class: 'DevelopersRecipientProvider']], + from: "Mr. Jenkins ", + subject: "Jenkins job ${env.JOB_NAME}#${env.BUILD_NUMBER} failed", + body: """ +There is a build failure in ${env.JOB_NAME}. + +Build: ${env.BUILD_URL} +Logs: ${env.BUILD_URL}console +Changes: ${env.BUILD_URL}changes + +-- +Mr. Jenkins +Director of Continuous Integration +""" + ) + } + } + + // If this build didn't fail, but there were failing tests, send an email to the list. + unstable { + script { + emailext( + to: "notifications@struts.apache.org", + recipientProviders: [[$class: 'DevelopersRecipientProvider']], + from: "Mr. Jenkins ", + subject: "Jenkins job ${env.JOB_NAME}#${env.BUILD_NUMBER} unstable", + body: """ +Some tests have failed in ${env.JOB_NAME}. + +Build: ${env.BUILD_URL} +Logs: ${env.BUILD_URL}console +Changes: ${env.BUILD_URL}changes + +-- +Mr. Jenkins +Director of Continuous Integration +""" + ) + } + } + + // Send an email, if the last build was not successful and this one is. + fixed { + script { + emailext( + to: "notifications@struts.apache.org", + recipientProviders: [[$class: 'DevelopersRecipientProvider']], + from: 'Mr. Jenkins ', + subject: "Jenkins job ${env.JOB_NAME}#${env.BUILD_NUMBER} back to normal", + body: """ +The build for ${env.JOB_NAME} completed successfully and is back to normal. + +Build: ${env.BUILD_URL} +Logs: ${env.BUILD_URL}console +Changes: ${env.BUILD_URL}changes + +-- +Mr. Jenkins +Director of Continuous Integration +""" + ) + } + } + } +} diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000000..261eeb9e9f --- /dev/null +++ b/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. diff --git a/README.md b/README.md index 6d0db9cc94..24e38d10fb 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,117 @@ + The Apache Struts web framework ------------------------------- -[![Build Status @ Jenkins](https://builds.apache.org/buildStatus/icon?job=Struts-JDK7-master)](https://builds.apache.org/view/S-Z/view/Struts/job/Struts-JDK7-master/) -[![Build Status @ Travis](https://travis-ci.org/apache/struts.svg?branch=master)](https://travis-ci.org/apache/struts) -[![Maven Central](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/badge.svg)](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/) +[![Build Status](https://ci-builds.apache.org/buildStatus/icon?job=Struts%2FStruts+Core%2Fmain)](https://ci-builds.apache.org/job/Struts/job/Struts%20Core/job/main/) +[![Java Build](https://github.com/apache/struts/actions/workflows/maven.yml/badge.svg)](https://github.com/apache/struts/actions/workflows/maven.yml) +[![Maven Central](https://maven-badges.sml.io/maven-central/org.apache.struts/struts2-core/badge.svg)](https://maven-badges.sml.io/maven-central/org.apache.struts/struts2-core/) +[![Javadocs](https://javadoc.io/badge/org.apache.struts/struts2-core.svg)](https://javadoc.io/doc/org.apache.struts/struts2-core) +[![Coverage](https://sonarcloud.io/api/project_badges/measure?project=apache_struts&metric=coverage)](https://sonarcloud.io/summary/new_code?id=apache_struts) +[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/apache/struts/badge)](https://deps.dev/maven/org.apache.struts%3Astruts2-core) +[![CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/6618/badge)](https://bestpractices.coreinfrastructure.org/projects/6618) [![License](http://img.shields.io/:license-apache-blue.svg)](http://www.apache.org/licenses/LICENSE-2.0.html) The Apache Struts web framework is a free open-source solution for creating Java web applications. -Web applications differ from conventional websites in that web applications can create a dynamic response. Many websites deliver only static pages. A web application can interact with databases and business logic engines to customize a response. +## Documentation -Web applications based on JavaServer Pages sometimes commingle database code, page design code, and control flow code. In practice, we find that unless these concerns are separated, larger applications become difficult to maintain. +More information can be found on the [homepage](https://struts.apache.org/). Please read the [Security Guide](https://struts.apache.org/security/), +and the [JavaDocs](https://struts.apache.org/maven/struts2-core/apidocs/index.html) can be browsed. +Questions related to the usage of Apache Struts should be posted to the [user mailing list](https://struts.apache.org/mail.html). -One way to separate concerns in a software application is to use a Model-View-Controller (MVC) architecture. The Model represents the business or database code, the View represents the page design code, and the Controller represents the navigational code. The Struts framework is designed to help developers create web applications that utilize a MVC architecture. +## Description + +Web applications differ from conventional websites in that web applications can create a dynamic response. Many websites +deliver only static pages. A web application can interact with databases and business logic engines to customize a response. + +Web applications based on JavaServer Pages sometimes commingle database code, page design code, and control flow code. +In practice, we find that unless these concerns are separated, larger applications become difficult to maintain. + +One way to separate concerns in a software application is to use a Model-View-Controller (MVC) architecture. The Model +represents the business or database code, the View represents the page design code, and the Controller represents +the navigational code. The Struts framework is designed to help developers create web applications that utilize +an MVC architecture. The framework provides three key components: -A “request” handler provided by the application developer that is mapped to a standard URI. A “response” handler that transfers control to another resource which completes the response. A tag library that helps developers create interactive form-based applications with server pages. The framework’s architecture and tags are buzzword compliant. Struts works well with conventional REST applications and with technologies like SOAP and AJAX. +- A “request” handler provided by the application developer that is mapped to a standard URI. +- A “response” handler that transfers control to another resource which completes the response. +- A tag library that helps developers create interactive form-based applications with server pages. + +The framework’s architecture and tags are buzzword compliant. Struts works well +with conventional REST applications and with technologies like SOAP and AJAX. + +## The Apache Struts Project + +The Apache Struts Project is the open source community that creates and maintains the Apache Struts framework. +The project consists of a diverse group of volunteers who share common values regarding collaborative, community-based +open source development. The Apache Struts Project is proud to share these values with our parent organization: +The Apache Software Foundation. + +The project is called “Struts” because the framework is meant to furnish the “invisible underpinnings” that support +professional application development. Struts provides the glue that joins the various elements of the standard Java +platform into a coherent whole. Our goal is to leverage existing standards by producing the missing pieces we need to create +enterprise-grade applications that are easy to maintain over time. + +The Apache Struts Project offered two major versions of the Struts framework. Currently we are only maintaining the Struts 2 +version. It is recommended to upgrade all Struts 1.x applications to Struts 2. Please do not start new application development +using Struts 1.x, as we are no longer issuing security patches. + +Struts 2 was originally known as WebWork 2. After working independently for several years, the WebWork and Struts +communities joined forces to create Struts 2. The 2.x framework is the best choice for teams who value elegant solutions +to difficult problems. -The Apache Struts Project -------------------------- +## Why should you use Apache Struts? -The Apache Struts Project is the open source community that creates and maintains the Apache Struts framework. The project consists of a diverse group of volunteers who share common values regarding collaborative, community-based open source development. The Apache Struts Project is proud to share these values with our parent organization: The Apache Software Foundation. +Apache Struts is a modern, maintained and full-featured web framework. As it has been around for years and grown a huge user +base it is unlikely it will go away anytime soon. Not only that, we have dedicated users and developers +on the project. Apache Struts is licensed under the Apache License 2.0 and this will not change. We maintain a clean IP +and you are “safe” to use the project. Sometimes you are not “safe” to use a project when a company controls the SCM. +Access to Source Code doesn’t mean it is free. With Apache Struts, you are not only free to “do what you want with it”, +you can even contribute (which is not always the case). And best of all: you can become a part of the core team too. -The project is called “Struts” because the framework is meant to furnish the “invisible underpinnings” that support professional application development. Struts provides the glue that joins the various elements of the standard Java platform into a coherent whole. Our goal is to leverage existing standards by producing the missing pieces we need to create enterprise-grade applications that are easy to maintain over time. +It is usually very easy to integrate other technologies with Apache Struts. If you are using an ORM like Apache Cayenne, +Hibernate or JDBC, you will not have any restrictions. Apache Struts is not even tied too much to a frontend technology. +In old days it was JSP, then came Velocity and Freemarker. Nowadays you might build your web application with just static +HTML and AngularJS. Or you might want to use Sitemesh or Tiles. This all is no problem due to Struts' elegant and easy-to-use +extension mechanisms. -The Apache Struts Project offered two major versions of the Struts framework. Currently we are only maintaining the Struts 2 version. It is recommended to upgrade all Struts 1.x application to Struts 2. Please do not start new application development using Struts 1.x, as we are no longer issuing security patches. +Unlike other, component-oriented frameworks, we do not aim to hide the stateless nature of the web. We think it is +perfectly acceptable to build upon a Request/Response cycle. We also think the MVC pattern is not so bad, just because +it is old. In fact, we believe the Apache Struts architecture is clean and easy to understand. -Struts 2 was originally known as WebWork 2. After working independently for several years, the WebWork and Struts communities joined forces to create Struts 2. The 2.x framework is the best choice for teams who value elegant solutions to difficult problems. +Of course, if you wish to build components on the server side which render on the front end side, you will most likely +not want Struts. This is a different approach which promises to reduce the amount of HTML/JavaScript knowledge needed +and to create reusable components for the view layer. Projects like Wicket and Tapestry serve this purpose very well. +As with every framework, you need to decide if it makes sense for you to build components or if you prefer +the Struts approach. -Why should you use Apache Struts? ---------------------------------- +## Commercial Support -Apache Struts is a modern, maintained and full-featured web framework. It has been there for years and give the huge user base it is unlikely it will go away anytime soon in the future. Not only that we have dedicated users and developers on the project. Apache Struts is licensed to the Apache License 2.0 and this will not change. We maintain a clean IP and you are “safe” to use the project. Sometimes you are not “safe” to use a project when a company controls the SCM. Access to Source Code doesn’t mean it is free. With Apache Struts, you are not only free to “do what you want with it”, you can even contribute (which is not always the case). And best of it: you can become a part of the core team too. +The Apache Struts community does not offer commercial support by itself, but we maintain [a list of companies offering +commercial support on our website](https://struts.apache.org/commercial-support.html). -It is usually very easy to integrate other technologies with Apache Struts. If you are using an ORM like Apache Cayenne, Hibernate or JDBC you will not have any restrictions. Apache Struts is not even tied too much to a frontend technology. In old days it was JSP, then came Velocity and Freemarker. Nowadays you might build your web application with just static HTML and AngularJS. Or you want to use Sitemesh or Tiles. This all is no problem due to Struts elegant and easy to use extension mechanisms. +Some Apache Struts maintainers are working with [Tidelift](https://tidelift.com/) to provide commercial support and +invest paid working time in the improvement of the Apache Struts framework. For more information, visit +the [Tidelift resources regarding Apache Struts](https://tidelift.com/subscription/pkg/maven-org-apache-struts-struts2-core?utm_source=maven-org-apache-struts-struts2-core&utm_medium=referral&utm_campaign=readme) -Unlike other, component oriented frameworks, we do not aim to hide the stateless nature of the web. We think it is perfectly acceptable to build upon a Request/Response cycle. We also think the MVC pattern is not so bad, just because it is old. In fact, we believe the Apache Struts architecture is clean and easy to understand. +## Thank you -Of course, if you wish to build components on the server side which render on the front end side, you are most likely wrong with Struts. This is a different approach which promises to reduce the amount of HTML/JavaScript knowledge needed and to create reusable components for the view layer. Projects like Wicket and Tapestry serve this purpose very well. As with every framework you need to decide if it makes sense for you to build components or if you are better with the Struts-approach. +[YourKit](https://www.yourkit.com/) is kindly supporting open source projects with its full-featured Java Profiler. +YourKit is the creator of innovative and intelligent tools for profiling Java and .NET applications. +As an Apache committer, you can get a free license at [YourKit's open source sponsorship program](https://www.yourkit.com/java/profiler/purchase/#os_license). diff --git a/SECURITY.md b/SECURITY.md new file mode 100644 index 0000000000..3337463dd7 --- /dev/null +++ b/SECURITY.md @@ -0,0 +1,40 @@ +# Security Policy + +## Supported Versions + +Please visit the [Releases](https://struts.apache.org/releases.html#prior-releases) page to see full information about each version +and what potential vulnerability it can have: + +| Version | Supported | +|---------|--------------------| +| 7.x | :white_check_mark: | +| 6.7.x | :white_check_mark: | +| 2.5.x | ❌ | + +## Reporting New Security Issues with thr Apache Struts + +([original](https://struts.apache.org/security.html)) + +The Apache Struts project takes a very active stance in eliminating security problems +and denial of service attacks against applications using the Apache Struts framework. + +**We strongly encourage folks to report such security problems to our private security mailing list first, +before disclosing them in a public forum**. + +We cannot accept regular bug reports or other queries at this address, we ask that you use our +[issue tracker (JIRA)](https://issues.apache.org/jira/browse/WW) for those. + +``` +All mail sent to this address that does not relate to security problems in the Apache Struts source code will be ignored +``` + +Note that all networked servers are subject to denial of service attacks, and we cannot promise magic +workarounds to generic problems (such as a client streaming lots of data to your server, or requesting +the same URL repeatedly). In general, our philosophy is to avoid any attacks that can cause the server +to consume resources in a non-linear relationship to the size of inputs. + +The mailing address is: [security@struts.apache.org](mailto:security@struts.apache.org) + +[General network server security tips](http://httpd.apache.org/docs/trunk/misc/security_tips.html) + +[The Apache Security Team](http://www.apache.org/security/) diff --git a/apps/README.md b/apps/README.md new file mode 100644 index 0000000000..0036a0d3a1 --- /dev/null +++ b/apps/README.md @@ -0,0 +1,12 @@ +# Struts 2 Apps +These module consists of two example applications, which were built using the Apache Struts project. +One is an old-fashioned Web application and another is a modern REST based single page app. + +## Installation +Enter a given folder, either `showcase/` or `rest-showcase/` and start the app using Maven: + +``` +mvn jetty:run +``` + +then open your browser at http://localhost:8080 and navigate to a proper context. diff --git a/apps/pom.xml b/apps/pom.xml index cb8654620d..e156f1d6c8 100644 --- a/apps/pom.xml +++ b/apps/pom.xml @@ -1,8 +1,6 @@ @@ -46,14 +52,14 @@ copy-sources process-sources - + - + run @@ -78,14 +84,6 @@ WEB-INF/classes/LICENSE.txt,WEB-INF/classes/NOTICE.txt - - maven-site-plugin - - true - true - false - - ${project.artifactId} @@ -96,18 +94,12 @@ org.apache.struts struts2-core - ${project.version} - org.springframework spring-test - ${struts2.springPlatformVersion} test - - UTF-8 - diff --git a/apps/rest-showcase/pom.xml b/apps/rest-showcase/pom.xml index 1f384d4a2e..3e689b7f0c 100644 --- a/apps/rest-showcase/pom.xml +++ b/apps/rest-showcase/pom.xml @@ -1,8 +1,6 @@ org.apache.logging.log4j log4j-api - ${log4j2.version} org.apache.logging.log4j log4j-core - ${log4j2.version} @@ -70,26 +71,31 @@ net.sourceforge.jwebunit jwebunit-core - 1.4.1 + 3.3 test + - commons-httpclient - commons-httpclient - 3.1 + org.htmlunit + htmlunit test net.sourceforge.jwebunit jwebunit-htmlunit-plugin - 1.4.1 + 3.3 test xom xom + + + net.sourceforge.htmlunit + htmlunit + @@ -99,18 +105,12 @@ struts2-rest-showcase - org.mortbay.jetty + org.eclipse.jetty jetty-maven-plugin - 8.1.16.v20140903 + 11.0.18 CTRL+C 8999 - - - xwork.loggerFactory - com.opensymphony.xwork2.util.logging.log4j2.Log4j2LoggerFactory - - 10 ${basedir}/src/main/webapp/ @@ -122,6 +122,7 @@ maven-surefire-plugin + @{argLine} it/** **/*$* diff --git a/apps/rest-showcase/src/main/java/org/demo/rest/example/IndexController.java b/apps/rest-showcase/src/main/java/org/demo/rest/example/IndexController.java index 0e6d40355e..eb330e8af2 100644 --- a/apps/rest-showcase/src/main/java/org/demo/rest/example/IndexController.java +++ b/apps/rest-showcase/src/main/java/org/demo/rest/example/IndexController.java @@ -1,3 +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. + */ package org.demo.rest.example; import org.apache.struts2.convention.annotation.Action; diff --git a/apps/rest-showcase/src/main/java/org/demo/rest/example/Order.java b/apps/rest-showcase/src/main/java/org/demo/rest/example/Order.java index 2c5e3f8224..ad368bf7d4 100644 --- a/apps/rest-showcase/src/main/java/org/demo/rest/example/Order.java +++ b/apps/rest-showcase/src/main/java/org/demo/rest/example/Order.java @@ -1,3 +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. + */ package org.demo.rest.example; import org.apache.commons.lang3.builder.EqualsBuilder; diff --git a/apps/rest-showcase/src/main/java/org/demo/rest/example/OrdersController.java b/apps/rest-showcase/src/main/java/org/demo/rest/example/OrdersController.java index 8ccad7e7ad..64ef99dfa5 100644 --- a/apps/rest-showcase/src/main/java/org/demo/rest/example/OrdersController.java +++ b/apps/rest-showcase/src/main/java/org/demo/rest/example/OrdersController.java @@ -1,29 +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.demo.rest.example; -import java.util.Collection; - +import org.apache.struts2.ModelDriven; +import org.apache.struts2.Validateable; +import org.apache.struts2.ValidationAwareSupport; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.struts2.convention.annotation.Result; +import org.apache.struts2.convention.annotation.Results; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import org.apache.struts2.rest.DefaultHttpHeaders; import org.apache.struts2.rest.HttpHeaders; -import org.apache.struts2.convention.annotation.Results; -import org.apache.struts2.convention.annotation.Result; -import com.opensymphony.xwork2.ModelDriven; -import com.opensymphony.xwork2.Validateable; -import com.opensymphony.xwork2.ValidationAwareSupport; +import java.util.Collection; @Results({ @Result(name="success", type="redirectAction", params = {"actionName" , "orders"}) }) -public class OrdersController extends ValidationAwareSupport implements ModelDriven, Validateable{ +public class OrdersController extends ValidationAwareSupport implements ModelDriven, Validateable { private static final Logger log = LogManager.getLogger(OrdersController.class); private Order model = new Order(); private String id; private Collection list; - private OrdersService ordersService = new OrdersService(); + private final OrdersService ordersService = new OrdersService(); // GET /orders/1 public HttpHeaders show() { @@ -36,7 +54,7 @@ public HttpHeaders index() { return new DefaultHttpHeaders("index") .disableCaching(); } - + // GET /orders/1/edit public String edit() { return "edit"; @@ -83,13 +101,15 @@ public void validate() { } } + @StrutsParameter public void setId(String id) { if (id != null) { this.model = ordersService.get(id); } this.id = id; } - + + @Override public Object getModel() { return (list != null ? list : model); } diff --git a/apps/rest-showcase/src/main/java/org/demo/rest/example/OrdersService.java b/apps/rest-showcase/src/main/java/org/demo/rest/example/OrdersService.java index 1f36aa4e2a..431fdcf57c 100644 --- a/apps/rest-showcase/src/main/java/org/demo/rest/example/OrdersService.java +++ b/apps/rest-showcase/src/main/java/org/demo/rest/example/OrdersService.java @@ -1,10 +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.demo.rest.example; -import java.util.*; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class OrdersService { - private static Map orders = new HashMap(); + private static final Map orders = new HashMap<>(); private static int nextId = 6; static { orders.put("3", new Order("3", "Bob", 33)); diff --git a/apps/rest-showcase/src/main/resources/log4j2.xml b/apps/rest-showcase/src/main/resources/log4j2.xml index 33a843219f..f6836e06ae 100644 --- a/apps/rest-showcase/src/main/resources/log4j2.xml +++ b/apps/rest-showcase/src/main/resources/log4j2.xml @@ -1,4 +1,24 @@ + @@ -6,7 +26,6 @@ - diff --git a/apps/rest-showcase/src/main/resources/struts.xml b/apps/rest-showcase/src/main/resources/struts.xml index 16d073978a..5a49e0e0d7 100644 --- a/apps/rest-showcase/src/main/resources/struts.xml +++ b/apps/rest-showcase/src/main/resources/struts.xml @@ -1,8 +1,6 @@ + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> @@ -34,7 +32,13 @@ + + + index,show,create,update,destroy,deleteConfirm,edit,editNew - \ No newline at end of file + diff --git a/apps/rest-showcase/src/main/resources/velocity.properties b/apps/rest-showcase/src/main/resources/velocity.properties index 6299831743..5a0d48b743 100644 --- a/apps/rest-showcase/src/main/resources/velocity.properties +++ b/apps/rest-showcase/src/main/resources/velocity.properties @@ -1 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# runtime.log.logsystem.class=org.apache.velocity.runtime.log.NullLogChute diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp index 98f3c39c14..11d02a344a 100644 --- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp +++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-deleteConfirm.jsp @@ -1,3 +1,23 @@ +<%-- +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT 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="s" uri="/struts-tags" %> @@ -7,14 +27,16 @@ Orders - - + + <%=((HttpServletRequest)request).getContextPath()%> + + diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp index d41071972f..f2376412fc 100644 --- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp +++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-edit.jsp @@ -1,3 +1,23 @@ +<%-- +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT 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="s" uri="/struts-tags" %> @@ -7,14 +27,16 @@ Orders - - + + <%=((HttpServletRequest)request).getContextPath()%> + + diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp index 080d79a3ec..2951e5a190 100644 --- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp +++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-editNew.jsp @@ -1,3 +1,23 @@ +<%-- +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT 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="s" uri="/struts-tags" %> @@ -7,13 +27,16 @@ Orders - - + + <%=((HttpServletRequest)request).getContextPath()%> + + + diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp index 466699a333..7bbbc2ddce 100644 --- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp +++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-index.jsp @@ -1,3 +1,23 @@ +<%-- +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT 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="s" uri="/struts-tags" %> @@ -7,14 +27,16 @@ Orders - - + + <%=((HttpServletRequest)request).getContextPath()%> + + diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp index f4b6f047f9..03153ff55e 100644 --- a/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp +++ b/apps/rest-showcase/src/main/webapp/WEB-INF/content/orders-show.jsp @@ -1,3 +1,23 @@ +<%-- +/* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT 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="s" uri="/struts-tags" %> @@ -7,14 +27,16 @@ Orders - - + + <%=((HttpServletRequest)request).getContextPath()%> + + diff --git a/apps/rest-showcase/src/main/webapp/WEB-INF/web.xml b/apps/rest-showcase/src/main/webapp/WEB-INF/web.xml index ddd928db98..10e50dd165 100644 --- a/apps/rest-showcase/src/main/webapp/WEB-INF/web.xml +++ b/apps/rest-showcase/src/main/webapp/WEB-INF/web.xml @@ -1,15 +1,34 @@ - - + - - Struts 2 Rest Example + xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee + http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd" + version="3.1"> + Struts 2 Rest Example - - + + action2 org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter diff --git a/apps/rest-showcase/src/main/webapp/css/app.css b/apps/rest-showcase/src/main/webapp/css/app.css index 266479a389..f77ce39f78 100644 --- a/apps/rest-showcase/src/main/webapp/css/app.css +++ b/apps/rest-showcase/src/main/webapp/css/app.css @@ -1,3 +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. + */ .form-group .errorMessage { list-style: none; font-weight: bold; diff --git a/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/GetOrdersTest.java b/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/GetOrdersTest.java index 9a2b8a731c..0fe39da4a3 100644 --- a/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/GetOrdersTest.java +++ b/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/GetOrdersTest.java @@ -1,30 +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 it.org.apache.struts2.rest.example; -import net.sourceforge.jwebunit.junit.WebTestCase; +import org.junit.Before; +import org.junit.Test; -public class GetOrdersTest extends WebTestCase { +import static net.sourceforge.jwebunit.junit.JWebUnit.assertTextNotPresent; +import static net.sourceforge.jwebunit.junit.JWebUnit.assertTextPresent; +import static net.sourceforge.jwebunit.junit.JWebUnit.beginAt; +import static net.sourceforge.jwebunit.junit.JWebUnit.getTestContext; +public class GetOrdersTest { + + @Before public void setUp() throws Exception { getTestContext().setBaseUrl(ParameterUtils.getBaseUrl()); } - + @Test public void testGetOrders() { beginAt("/orders/3"); assertTextPresent("Bob"); assertTextNotPresent("Sarah"); } + @Test public void testGetOrdersInHtml() { beginAt("/orders/3.xhtml"); assertTextPresent("Bob"); } + @Test public void testGetOrdersInXml() { beginAt("/orders/3.xml"); assertTextPresent("Bob"); } + @Test public void testGetOrdersInJson() { beginAt("/orders/3.json"); assertTextPresent("\"clientName\":\"Bob\""); diff --git a/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/ListOrdersTest.java b/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/ListOrdersTest.java index 75dfcdbb48..5fc5651716 100644 --- a/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/ListOrdersTest.java +++ b/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/ListOrdersTest.java @@ -1,14 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ package it.org.apache.struts2.rest.example; -import net.sourceforge.jwebunit.junit.WebTestCase; +import org.junit.Before; +import org.junit.Test; -public class ListOrdersTest extends WebTestCase { +import static net.sourceforge.jwebunit.junit.JWebUnit.assertTextPresent; +import static net.sourceforge.jwebunit.junit.JWebUnit.beginAt; +import static net.sourceforge.jwebunit.junit.JWebUnit.getTestContext; +public class ListOrdersTest { + + @Before public void setUp() throws Exception { getTestContext().setBaseUrl(ParameterUtils.getBaseUrl()); } - + @Test public void testListOrders() { beginAt("/orders"); assertTextPresent("Bob"); @@ -16,6 +40,7 @@ public void testListOrders() { assertTextPresent("Jim"); } + @Test public void testListOrdersInHtml() { beginAt("/orders.xhtml"); assertTextPresent("Bob"); @@ -23,6 +48,7 @@ public void testListOrdersInHtml() { assertTextPresent("Jim"); } + @Test public void testListOrdersInXml() { beginAt("/orders.xml"); assertTextPresent("Bob"); @@ -30,6 +56,7 @@ public void testListOrdersInXml() { assertTextPresent("Jim"); } + @Test public void testListOrdersInJson() { beginAt("/orders.json"); assertTextPresent("\"clientName\":\"Bob\""); diff --git a/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/ParameterUtils.java b/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/ParameterUtils.java index f5eb8ee83b..f7c935f2ec 100644 --- a/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/ParameterUtils.java +++ b/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/ParameterUtils.java @@ -1,3 +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. + */ package it.org.apache.struts2.rest.example; public class ParameterUtils { diff --git a/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/PostOrderTest.java b/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/PostOrderTest.java index 30df79c853..fa7fd97f12 100644 --- a/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/PostOrderTest.java +++ b/apps/rest-showcase/src/test/java/it/org/apache/struts2/rest/example/PostOrderTest.java @@ -1,21 +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 it.org.apache.struts2.rest.example; -import net.sourceforge.jwebunit.junit.WebTestCase; -import org.apache.commons.httpclient.HttpClient; -import org.apache.commons.httpclient.methods.PostMethod; -import org.apache.commons.httpclient.methods.StringRequestEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpPost; +import org.apache.http.entity.StringEntity; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; +import org.htmlunit.FailingHttpStatusCodeException; +import org.junit.Before; +import org.junit.Test; import java.io.IOException; -import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException; +import static net.sourceforge.jwebunit.junit.JWebUnit.assertLinkNotPresentWithText; +import static net.sourceforge.jwebunit.junit.JWebUnit.assertTextFieldEquals; +import static net.sourceforge.jwebunit.junit.JWebUnit.assertTextPresent; +import static net.sourceforge.jwebunit.junit.JWebUnit.beginAt; +import static net.sourceforge.jwebunit.junit.JWebUnit.getTestContext; +import static net.sourceforge.jwebunit.junit.JWebUnit.setTextField; +import static net.sourceforge.jwebunit.junit.JWebUnit.setWorkingForm; +import static net.sourceforge.jwebunit.junit.JWebUnit.submit; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertTrue; -public class PostOrderTest extends WebTestCase { +public class PostOrderTest { + @Before public void setUp() throws Exception { getTestContext().setBaseUrl(ParameterUtils.getBaseUrl()); } - + @Test public void testPostOrder() { beginAt("/orders/new"); setWorkingForm(0); @@ -26,6 +59,7 @@ public void testPostOrder() { assertLinkNotPresentWithText("Back to Orders"); } + @Test public void testPostOrderWithErrors() { beginAt("/orders/new"); setWorkingForm(0); @@ -39,6 +73,7 @@ public void testPostOrderWithErrors() { assertTextFieldEquals("amount", "321"); } + @Test public void testPostOrderInHtml() { beginAt("/orders/new.xhtml"); setWorkingForm(0); @@ -53,69 +88,55 @@ public void testPostOrderInHtml() { assertLinkNotPresentWithText("Back to Orders"); } + @Test public void testPostOrderInXml() throws IOException { - HttpClient client = new HttpClient(); - PostMethod method = null; - try { - method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.xml"); - method.setRequestEntity(new StringRequestEntity("\n" + - "Test3\n" + - "3342\n" + - "")); - client.executeMethod(method); - assertEquals(201, method.getStatusCode()); - assertTrue(method.getResponseHeader("Location").getValue().startsWith(ParameterUtils.getBaseUrl()+"/orders/")); - } finally { - method.releaseConnection(); - } + CloseableHttpClient client = HttpClients.createDefault(); + HttpPost httpPost = new HttpPost(ParameterUtils.getBaseUrl() + "/orders.xml"); + httpPost.setEntity(new StringEntity("\n" + + "Test3\n" + + "3342\n" + + "")); + CloseableHttpResponse response = client.execute(httpPost); + assertEquals(201, response.getStatusLine().getStatusCode()); + assertTrue(response.getHeaders("Location")[0].getValue().startsWith(ParameterUtils.getBaseUrl() + "/orders/")); + client.close(); } + @Test public void testPostOrderInXmlWithBadData() throws IOException { - HttpClient client = new HttpClient(); - PostMethod method = null; - try { - method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.xml"); - method.setRequestEntity(new StringRequestEntity("\n" + - "3342\n" + - "")); - client.executeMethod(method); - assertEquals(400, method.getStatusCode()); - String response = method.getResponseBodyAsString(); - assertTrue(response.contains("The client name is empty")); - assertNull(method.getResponseHeader("Location")); - } finally { - method.releaseConnection(); - } + CloseableHttpClient client = HttpClients.createDefault(); + HttpPost httpPost = new HttpPost(ParameterUtils.getBaseUrl() + "/orders.xml"); + httpPost.setEntity(new StringEntity("\n" + + "3342\n" + + "")); + CloseableHttpResponse response = client.execute(httpPost); + assertEquals(400, response.getStatusLine().getStatusCode()); + assertTrue(response.toString().contains("The client name is empty")); + assertNull(response.getHeaders("Location")); + client.close(); } + @Test public void testPostOrderInJson() throws IOException { - HttpClient client = new HttpClient(); - PostMethod method = null; - try { - method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.json"); - method.setRequestEntity(new StringRequestEntity("{\"amount\":33,\"clientName\":\"Test4\"}")); - client.executeMethod(method); - assertEquals(201, method.getStatusCode()); - assertTrue(method.getResponseHeader("Location").getValue().startsWith(ParameterUtils.getBaseUrl()+"/orders/")); - } finally { - method.releaseConnection(); - } + CloseableHttpClient client = HttpClients.createDefault(); + HttpPost httpPost = new HttpPost(ParameterUtils.getBaseUrl() + "/orders.json"); + httpPost.setEntity(new StringEntity("{\"amount\":33,\"clientName\":\"Test4\"}")); + CloseableHttpResponse response = client.execute(httpPost); + assertEquals(201, response.getStatusLine().getStatusCode()); + assertTrue(response.getHeaders("Location")[0].getValue().startsWith(ParameterUtils.getBaseUrl() + "/orders/")); + client.close(); } + @Test public void testPostOrderInJsonWithBadData() throws IOException { - HttpClient client = new HttpClient(); - PostMethod method = null; - try { - method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.json"); - method.setRequestEntity(new StringRequestEntity("{\"amount\":33}")); - client.executeMethod(method); - String response = method.getResponseBodyAsString(); - assertEquals(400, method.getStatusCode()); - - assertEquals("{\"actionErrors\":[],\"fieldErrors\":{\"clientName\":[\"The client name is empty\"]}}", response); - assertNull(method.getResponseHeader("Location")); - } finally { - method.releaseConnection(); - } + CloseableHttpClient client = HttpClients.createDefault(); + HttpPost httpPost = new HttpPost(ParameterUtils.getBaseUrl() + "/orders.json"); + httpPost.setEntity(new StringEntity("{\"amount\":33}")); + CloseableHttpResponse response = client.execute(httpPost); + assertEquals(400, response.getStatusLine().getStatusCode()); + assertTrue(response.toString() + .contains("{\"actionErrors\":[],\"fieldErrors\":{\"clientName\":[\"The client name is empty\"]}}")); + assertNull(response.getHeaders("Location")); + client.close(); } } \ No newline at end of file diff --git a/apps/showcase/pom.xml b/apps/showcase/pom.xml index cbd484896c..9c8acc4d2b 100644 --- a/apps/showcase/pom.xml +++ b/apps/showcase/pom.xml @@ -1,8 +1,6 @@ - org.apache.velocity - velocity + org.apache.logging.log4j + log4j-slf4j-impl - org.apache.velocity - velocity-tools + org.sitemesh + sitemesh + 3.2.2 - - opensymphony - sitemesh - - - uk.ltd.getahead - dwr - - - commons-fileupload - commons-fileupload - + + junit + junit + test + - net.sourceforge.jwebunit - jwebunit-core - 1.4.1 + org.assertj + assertj-core test - - commons-httpclient - commons-httpclient - 3.1 - test - + + org.htmlunit + htmlunit + test + + - net.sourceforge.jwebunit - jwebunit-htmlunit-plugin - 1.4.1 - test + org.hibernate.validator + hibernate-validator + ${hibernate-validator.version} - xom - xom + jakarta.validation + jakarta.validation-api - + - org.hibernate - hibernate-validator - 5.1.3.Final + org.codehaus.groovy + groovy-jsr223 + 3.0.22 - - - - javax.servlet - javax.servlet-api - 3.1.0 - test - - - org.mortbay.jetty + org.apache.maven.plugins + maven-dependency-plugin + + + + copy-dependencies + package + + copy + + + ${project.build.directory}/extraclasspath + + + org.apache.struts + struts2-velocity-tools-view-jakarta + struts2-velocity-tools-view-jakarta.jar + + + org.apache.struts + struts2-velocity-tools-jsp-jakarta + struts2-velocity-tools-jsp-jakarta.jar + + + false + false + true + + + + + + org.apache.maven.plugins + maven-failsafe-plugin + 3.5.2 + + + it.org.apache.struts2.showcase.*Test + + + 8090 + + + + + integration-test + + integration-test + + + + verify + + verify + + + + + + org.eclipse.jetty jetty-maven-plugin - 8.1.16.v20140903 + 11.0.18 CTRL+C 8999 - - log4j.configuration - file:${basedir}/src/main/resources/log4j.properties - slf4j false - 10 - ${basedir}/src/main/webapp/ - - /struts2-showcase - ${basedir}/src/main/webapp/WEB-INF/web.xml - + + 8090 + + 10 + + + ${project.build.directory}/extraclasspath/struts2-velocity-tools-view-jakarta.jar, + ${project.build.directory}/extraclasspath/struts2-velocity-tools-jsp-jakarta + + /struts2-showcase + ${basedir}/src/main/webapp/WEB-INF/web.xml + + + + start-jetty + pre-integration-test + + + stop + start + + + + stop-jetty + post-integration-test + + stop + + + maven-surefire-plugin + @{argLine} it/** **/*$* diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java index 21aa14840e..df1fbe5116 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/DateAction.java @@ -20,7 +20,7 @@ */ package org.apache.struts2.showcase; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; import java.text.DateFormat; import java.util.Calendar; diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java index 422b483cbc..67bdba155d 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/DynamicTreeSelectAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import org.apache.struts2.showcase.ajax.tree.Category; //START SNIPPET: treeExampleDynamicJavaSelected @@ -30,7 +31,7 @@ public class DynamicTreeSelectAction extends ActionSupport { private long nodeId; private Category currentCategory; - + @StrutsParameter public void setNodeId(long nodeId) { this.nodeId = nodeId; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java index b56618eeba..e82d72187b 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfOptiontransferselectAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -74,6 +75,7 @@ public List getFavouriteCartoonCharacters() { return _favouriteCartoonCharactersKeys; } + @StrutsParameter public void setFavouriteCartoonCharacters(List favouriteCartoonCharacters) { _favouriteCartoonCharactersKeys = favouriteCartoonCharacters; } @@ -82,6 +84,7 @@ public List getNotFavouriteCartoonCharacters() { return _notFavouriteCartoonCharactersKeys; } + @StrutsParameter public void setNotFavouriteCartoonCharacters(List notFavouriteCartoonCharacters) { _notFavouriteCartoonCharactersKeys = notFavouriteCartoonCharacters; } @@ -108,6 +111,7 @@ public List getFavouriteCars() { return _favouriteCarsKeys; } + @StrutsParameter public void setFavouriteCars(List favouriteCars) { _favouriteCarsKeys = favouriteCars; } @@ -116,6 +120,7 @@ public List getNotFavouriteCars() { return _notFavouriteCarsKeys; } + @StrutsParameter public void setNotFavouriteCars(List notFavouriteCars) { _notFavouriteCarsKeys = notFavouriteCars; } @@ -142,6 +147,7 @@ public List getFavouriteMotorcycles() { return _favouriteMotorcyclesKeys; } + @StrutsParameter public void setFavouriteMotorcycles(List favouriteMotorcycles) { _favouriteMotorcyclesKeys = favouriteMotorcycles; } @@ -150,6 +156,7 @@ public List getNotFavouriteMotorcycles() { return _notFavouriteMotorcyclesKeys; } + @StrutsParameter public void setNotFavouriteMotorcycles(List notFavouriteMotorcycles) { _notFavouriteMotorcyclesKeys = notFavouriteMotorcycles; } @@ -176,6 +183,7 @@ public List getFavouriteCountries() { return _favouriteCountriesKeys; } + @StrutsParameter public void setFavouriteCountries(List favouriteCountries) { _favouriteCountriesKeys = favouriteCountries; } @@ -184,6 +192,7 @@ public List getNotFavouriteCountries() { return _notFavouriteCountriesKeys; } + @StrutsParameter public void setNotFavouriteCountries(List notFavouriteCountries) { _notFavouriteCountriesKeys = notFavouriteCountries; } @@ -205,6 +214,7 @@ public List getFavouriteSports() { return _favouriteSportsKeys; } + @StrutsParameter public void setFavouriteSports(List favouriteSportsKeys) { this._favouriteSportsKeys = favouriteSportsKeys; } @@ -213,6 +223,7 @@ public List getNonFavouriteSports() { return _nonFavouriteSportsKeys; } + @StrutsParameter public void setNonFavouriteSports(List notFavouriteSportsKeys) { this._nonFavouriteSportsKeys = notFavouriteSportsKeys; } @@ -222,6 +233,7 @@ public List getPrioritisedFavouriteCartoonCharacters() { return _prioritisedFavouriteCartoonCharacters; } + @StrutsParameter public void setPrioritisedFavouriteCartoonCharacters(List prioritisedFavouriteCartoonCharacters) { _prioritisedFavouriteCartoonCharacters = prioritisedFavouriteCartoonCharacters; } @@ -230,6 +242,7 @@ public List getPrioritisedFavouriteCars() { return _prioritisedFavouriteCars; } + @StrutsParameter public void setPrioritisedFavouriteCars(List prioritisedFavouriteCars) { _prioritisedFavouriteCars = prioritisedFavouriteCars; } @@ -239,6 +252,7 @@ public List getPrioritisedFavouriteCountries() { return _prioritisedFavouriteCountries; } + @StrutsParameter public void setPrioritisedFavouriteCountries(List prioritisedFavouriteCountries) { _prioritisedFavouriteCountries = prioritisedFavouriteCountries; } @@ -264,12 +278,13 @@ public List getFavouriteCities() { return _favouriteCities; } + @StrutsParameter public void setFavouriteCities(List favouriteCities) { this._favouriteCities = favouriteCities; } // actions - + @Override public String input() throws Exception { return SUCCESS; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java index 1e106691da..e4a0667a32 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/LotsOfRichtexteditorAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; /** * @@ -36,6 +37,7 @@ public String getDescription1() { return this.description1; } + @StrutsParameter public void setDescription1(String description1) { this.description1 = description1; } @@ -45,6 +47,7 @@ public String getDescription2() { return this.description2; } + @StrutsParameter public void setDescription2(String description2) { this.description2 = description2; } @@ -54,6 +57,7 @@ public String getDescription3() { return this.description3; } + @StrutsParameter public void setDescription3(String description3) { this.description3 = description3; } @@ -63,11 +67,12 @@ public String getDescription4() { return this.description4; } + @StrutsParameter public void setDescription4(String description4) { this.description4 = description4; } - + @Override public String input() throws Exception { return SUCCESS; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java index edbe4ae2b1..7f0d683940 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/MoreSelectsAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.ArrayList; import java.util.LinkedHashMap; @@ -36,6 +37,7 @@ public class MoreSelectsAction extends ActionSupport { private List _prioritisedFavouriteCars; private List _prioritisedFavouriteCountries; private List favouriteNumbers; + private List favouriteCities; // Cartoon Characters @@ -74,11 +76,11 @@ public List getDefaultFavouriteNumbers() { return list; } - public List getPrioritisedFavouriteCartoonCharacters() { return _prioritisedFavouriteCartoonCharacters; } + @StrutsParameter public void setPrioritisedFavouriteCartoonCharacters(List prioritisedFavouriteCartoonCharacters) { _prioritisedFavouriteCartoonCharacters = prioritisedFavouriteCartoonCharacters; } @@ -87,15 +89,16 @@ public List getPrioritisedFavouriteCars() { return _prioritisedFavouriteCars; } + @StrutsParameter public void setPrioritisedFavouriteCars(List prioritisedFavouriteCars) { _prioritisedFavouriteCars = prioritisedFavouriteCars; } - public List getPrioritisedFavouriteCountries() { return _prioritisedFavouriteCountries; } + @StrutsParameter public void setPrioritisedFavouriteCountries(List prioritisedFavouriteCountries) { _prioritisedFavouriteCountries = prioritisedFavouriteCountries; } @@ -104,6 +107,7 @@ public List getFavouriteNumbers() { return favouriteNumbers; } + @StrutsParameter public void setFavouriteNumbers(List favouriteNumbers) { this.favouriteNumbers = favouriteNumbers; } @@ -124,8 +128,17 @@ public List getDefaultFavouriteCities() { return list; } - // actions + public List getFavouriteCities() { + return favouriteCities; + } + @StrutsParameter + public void setFavouriteCities(List favouriteCities) { + this.favouriteCities = favouriteCities; + } + + // actions + @Override public String input() throws Exception { return SUCCESS; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowAjaxDynamicTreeAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowAjaxDynamicTreeAction.java index 40ec4b72ca..c2bab811d0 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowAjaxDynamicTreeAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowAjaxDynamicTreeAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import org.apache.struts2.showcase.ajax.tree.Category; public class ShowAjaxDynamicTreeAction extends ActionSupport { @@ -34,6 +35,7 @@ public int getNodeId() { return nodeId; } + @StrutsParameter public void setNodeId(int nodeId) { this.nodeId = nodeId; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java index cec9974658..22561463e5 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/ShowDynamicTreeAction.java @@ -20,7 +20,7 @@ */ package org.apache.struts2.showcase; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; import org.apache.struts2.showcase.ajax.tree.Category; // START SNIPPET: treeExampleDynamicJavaShow diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java index ca5aecbb7a..da7373de8d 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/UITagExample.java @@ -20,13 +20,19 @@ */ package org.apache.struts2.showcase; -import com.opensymphony.xwork2.ActionSupport; -import com.opensymphony.xwork2.Validateable; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.Validateable; +import org.apache.struts2.util.ValueStack; import org.apache.struts2.ServletActionContext; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.io.File; -import java.util.*; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; /** */ @@ -89,6 +95,7 @@ public List getLeftSideCartoonCharacters() { return leftSideCartoonCharacters; } + @StrutsParameter public void setLeftSideCartoonCharacters(List leftSideCartoonCharacters) { this.leftSideCartoonCharacters = leftSideCartoonCharacters; } @@ -98,6 +105,7 @@ public List getRightSideCartoonCharacters() { return rightSideCartoonCharacters; } + @StrutsParameter public void setRightSideCartoonCharacters(List rightSideCartoonCharacters) { this.rightSideCartoonCharacters = rightSideCartoonCharacters; } @@ -107,6 +115,7 @@ public String getFavouriteVehicalType() { return favouriteVehicalType; } + @StrutsParameter public void setFavouriteVehicalType(String favouriteVehicalType) { this.favouriteVehicalType = favouriteVehicalType; } @@ -115,6 +124,7 @@ public String getFavouriteVehicalSpecific() { return favouriteVehicalSpecific; } + @StrutsParameter public void setFavouriteVehicalSpecific(String favouriteVehicalSpecific) { this.favouriteVehicalSpecific = favouriteVehicalSpecific; } @@ -145,6 +155,7 @@ public String getName() { return name; } + @StrutsParameter public void setName(String name) { this.name = name; } @@ -153,6 +164,7 @@ public Date getBirthday() { return birthday; } + @StrutsParameter public void setBirthday(Date birthday) { this.birthday = birthday; } @@ -161,6 +173,7 @@ public String getBio() { return bio; } + @StrutsParameter public void setBio(String bio) { this.bio = bio; } @@ -169,6 +182,7 @@ public String getFavouriteColor() { return favouriteColor; } + @StrutsParameter public void setFavouriteColor(String favoriteColor) { this.favouriteColor = favoriteColor; } @@ -177,6 +191,7 @@ public List getFriends() { return friends; } + @StrutsParameter public void setFriends(List friends) { this.friends = friends; } @@ -185,6 +200,7 @@ public String getBestFriend() { return bestFriend; } + @StrutsParameter public void setBestFriend(String bestFriend) { this.bestFriend = bestFriend; } @@ -193,6 +209,7 @@ public boolean isLegalAge() { return legalAge; } + @StrutsParameter public void setLegalAge(boolean legalAge) { this.legalAge = legalAge; } @@ -201,6 +218,7 @@ public String getState() { return state; } + @StrutsParameter public void setState(String state) { this.state = state; } @@ -209,10 +227,12 @@ public String getRegion() { return region; } + @StrutsParameter public void setRegion(String region) { this.region = region; } + @StrutsParameter public void setPicture(File picture) { this.picture = picture; } @@ -221,14 +241,17 @@ public File getPicture() { return this.picture; } + @StrutsParameter public void setPictureContentType(String pictureContentType) { this.pictureContentType = pictureContentType; } + @StrutsParameter public void setPictureFileName(String pictureFileName) { this.pictureFileName = pictureFileName; } + @StrutsParameter public void setFavouriteLanguage(String favouriteLanguage) { this.favouriteLanguage = favouriteLanguage; } @@ -237,7 +260,7 @@ public String getFavouriteLanguage() { return favouriteLanguage; } - + @StrutsParameter public void setThoughts(String thoughts) { this.thoughts = thoughts; } @@ -250,6 +273,7 @@ public Date getWakeup() { return wakeup; } + @StrutsParameter public void setWakeup(Date wakeup) { this.wakeup = wakeup; } @@ -303,6 +327,7 @@ public String getDescription() { return this.description; } + @Override public boolean equals(Object obj) { if (!(obj instanceof VehicalType)) { return false; @@ -311,6 +336,7 @@ public boolean equals(Object obj) { } } + @Override public int hashCode() { return key.hashCode(); } @@ -334,6 +360,7 @@ public String getDescription() { return this.description; } + @Override public boolean equals(Object obj) { if (!(obj instanceof VehicalSpecific)) { return false; @@ -342,6 +369,7 @@ public boolean equals(Object obj) { } } + @Override public int hashCode() { return key.hashCode(); } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java index 42e51a5c8e..871136c64c 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/AbstractCRUDAction.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,9 +18,10 @@ */ package org.apache.struts2.showcase.action; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import org.apache.struts2.showcase.dao.Dao; import org.apache.struts2.showcase.model.IdEntity; @@ -35,62 +34,62 @@ public abstract class AbstractCRUDAction extends ActionSupport { - private static final Logger log = LogManager.getLogger(AbstractCRUDAction.class); - - private Collection availableItems; - private String[] toDelete; + private static final Logger log = LogManager.getLogger(AbstractCRUDAction.class); - protected abstract Dao getDao(); + private Collection availableItems; + private String[] toDelete; + protected abstract Dao getDao(); - public Collection getAvailableItems() { - return availableItems; - } + public Collection getAvailableItems() { + return availableItems; + } - public String[] getToDelete() { - return toDelete; - } + public String[] getToDelete() { + return toDelete; + } - public void setToDelete(String[] toDelete) { - this.toDelete = toDelete; - } + @StrutsParameter + public void setToDelete(String[] toDelete) { + this.toDelete = toDelete; + } - public String list() throws Exception { - this.availableItems = getDao().findAll(); - if (log.isDebugEnabled()) { - log.debug("AbstractCRUDAction - [list]: " + (availableItems != null ? "" + availableItems.size() : "no") + " items found"); - } - return execute(); - } + public String list() throws Exception { + this.availableItems = getDao().findAll(); + if (log.isDebugEnabled()) { + log.debug("AbstractCRUDAction - [list]: " + (availableItems != null ? "" + availableItems.size() : "no") + " items found"); + } + return execute(); + } - public String delete() throws Exception { - if (toDelete != null) { - int count = 0; - for (int i = 0, j = toDelete.length; i < j; i++) { - count = count + getDao().delete(toDelete[i]); - } - if (log.isDebugEnabled()) { - log.debug("AbstractCRUDAction - [delete]: " + count + " items deleted."); - } - } - return SUCCESS; - } + public String delete() throws Exception { + if (toDelete != null) { + int count = 0; + for (String s : toDelete) { + count = count + getDao().delete(s); + } + if (log.isDebugEnabled()) { + log.debug("AbstractCRUDAction - [delete]: {} items deleted.", count); + } + } + return SUCCESS; + } - /** - * Utility method for fetching already persistent object from storage for usage in params-prepare-params cycle. - * - * @param tryId The id to try to get persistent object for - * @param tryObject The object, induced by first params invocation, possibly containing id to try to get persistent - * object for - * @return The persistent object, if found. null otherwise. - */ - protected IdEntity fetch(Serializable tryId, IdEntity tryObject) { - IdEntity result = null; - if (tryId != null) { - result = getDao().get(tryId); - } else if (tryObject != null) { - result = getDao().get(tryObject.getId()); - } - return result; - } + /** + * Utility method for fetching already persistent object from storage for usage in params-prepare-params cycle. + * + * @param tryId The id to try to get persistent object for + * @param tryObject The object, induced by first params invocation, possibly containing id to try to get persistent + * object for + * @return The persistent object, if found. null otherwise. + */ + protected IdEntity fetch(Serializable tryId, IdEntity tryObject) { + IdEntity result = null; + if (tryId != null) { + result = getDao().get(tryId); + } else if (tryObject != null) { + result = getDao().get(tryObject.getId()); + } + return result; + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java index 21159705f8..634b549efe 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/EmployeeAction.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,9 +18,10 @@ */ package org.apache.struts2.showcase.action; -import com.opensymphony.xwork2.Preparable; +import org.apache.struts2.Preparable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import org.apache.struts2.showcase.application.TestDataProvider; import org.apache.struts2.showcase.dao.Dao; import org.apache.struts2.showcase.dao.EmployeeDao; @@ -54,7 +53,7 @@ public class EmployeeAction extends AbstractCRUDAction implements Preparable { public String execute() throws Exception { if (getCurrentEmployee() != null && getCurrentEmployee().getOtherSkills() != null) { - setSelectedSkills(new ArrayList()); + setSelectedSkills(new ArrayList<>()); Iterator it = getCurrentEmployee().getOtherSkills().iterator(); while (it.hasNext()) { getSelectedSkills().add(((Skill) it.next()).getName()); @@ -75,10 +74,12 @@ public Long getEmpId() { return empId; } + @StrutsParameter public void setEmpId(Long empId) { this.empId = empId; } + @StrutsParameter(depth = 2) public Employee getCurrentEmployee() { return currentEmployee; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/ExampleAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/ExampleAction.java index 82d8d3231d..b8ef9bdb62 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/ExampleAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/ExampleAction.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,9 +18,13 @@ */ package org.apache.struts2.showcase.action; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; -import java.util.*; +import java.util.Arrays; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; public class ExampleAction extends ActionSupport { public static final String CONSTANT = "Struts Rocks!"; @@ -48,7 +50,7 @@ public Book getBook() { } public Map getBooks() { - Map books = new HashMap(); + Map books = new HashMap<>(); books.put("Iliad", new Book("Iliad", "Homer")); books.put("The Republic", new Book("The Replublic", "Plato")); books.put("Thus Spake Zarathustra", new Book("Thus Spake Zarathustra", @@ -81,4 +83,4 @@ public String getAuthor() { public void setAuthor(String author) { this.author = author; } -} \ No newline at end of file +} diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/JSPEvalAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/JSPEvalAction.java index cc370c8a6c..43e15e0134 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/JSPEvalAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/JSPEvalAction.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,11 +18,16 @@ */ package org.apache.struts2.showcase.action; -import com.opensymphony.xwork2.Action; -import com.opensymphony.xwork2.interceptor.annotations.After; +import org.apache.struts2.action.Action; +import org.apache.struts2.interceptor.annotations.After; import org.apache.struts2.ServletActionContext; +import org.apache.struts2.interceptor.parameter.StrutsParameter; -import java.io.*; +import java.io.BufferedWriter; +import java.io.File; +import java.io.FileOutputStream; +import java.io.FileWriter; +import java.io.IOException; import java.net.URL; /** @@ -64,6 +67,7 @@ public void cleanUp() throws IOException { } } + @StrutsParameter public void setJsp(String jsp) { this.jsp = jsp; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/ParamsAnnotationAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/ParamsAnnotationAction.java new file mode 100644 index 0000000000..351a6a24e7 --- /dev/null +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/ParamsAnnotationAction.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.struts2.showcase.action; + +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; +import org.apache.struts2.showcase.model.MyDto; + +import java.lang.reflect.Field; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import static java.util.Collections.singletonList; +import static java.util.Collections.singletonMap; + +/** + * This class supports {@link com.atlassian.confluence.stateless.webdriver.selenium3.security.StrutsParametersTest} + * which prevents critical security regressions. Do NOT modify without understanding the motivation behind the tests and + * the implications of any changes. + */ +public class ParamsAnnotationAction extends ActionSupport { + + @StrutsParameter + public String varToPrint; + + public String publicField = "no"; + + @StrutsParameter + public String publicFieldAnnotated = "no"; + + private String privateField = "no"; + + public int[] publicArray = new int[]{0}; + + @StrutsParameter(depth = 1) + public int[] publicArrayAnnotated = new int[]{0}; + + public List publicList = new ArrayList<>(singletonList("no")); + + @StrutsParameter(depth = 1) + public List publicListAnnotated = new ArrayList<>(singletonList("no")); + + private List privateList = new ArrayList<>(singletonList("no")); + + public Map publicMap = new HashMap<>(singletonMap("key", "no")); + + @StrutsParameter(depth = 1) + public Map publicMapAnnotated = new HashMap<>(singletonMap("key", "no")); + + public MyDto publicMyDto = new MyDto(); + + @StrutsParameter(depth = 2) + public MyDto publicMyDtoAnnotated = new MyDto(); + + @StrutsParameter(depth = 1) + public MyDto publicMyDtoAnnotatedDepthOne = new MyDto(); + + private MyDto privateMyDto = new MyDto(); + + public void setPrivateFieldMethod(String privateField) { + this.privateField = privateField; + } + + @StrutsParameter + public void setPrivateFieldMethodAnnotated(String privateField) { + this.privateField = privateField; + } + + public List getPrivateListMethod() { + return privateList; + } + + @StrutsParameter(depth = 1) + public List getPrivateListMethodAnnotated() { + return privateList; + } + + public MyDto getUnsafeMethodMyDto() { + return privateMyDto; + } + + @StrutsParameter(depth = 2) + public MyDto getSafeMethodMyDto() { + return privateMyDto; + } + + @StrutsParameter(depth = 1) + public MyDto getSafeMethodMyDtoDepthOne() { + return privateMyDto; + } + + public String renderVarToPrint() throws ReflectiveOperationException { + if (varToPrint == null) { + return "null"; + } + Field field = this.getClass().getDeclaredField(varToPrint); + field.setAccessible(true); + try { + return String.format("%s{%s}", varToPrint, + field.getType().isArray() ? stringifyArray(field.get(this)) : field.get(this)); + } finally { + field.setAccessible(false); + } + } + + private String stringifyArray(Object array) { + switch (array.getClass().getComponentType().getName()) { + case "int": + return Arrays.toString((int[]) array); + default: + return "TODO"; + } + } +} diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java index ebc1b0b486..651c3c86d6 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/action/SkillAction.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,9 +18,10 @@ */ package org.apache.struts2.showcase.action; -import com.opensymphony.xwork2.Preparable; +import org.apache.struts2.Preparable; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import org.apache.struts2.showcase.dao.Dao; import org.apache.struts2.showcase.dao.SkillDao; import org.apache.struts2.showcase.model.Skill; @@ -47,6 +46,7 @@ public class SkillAction extends AbstractCRUDAction implements Preparable { * * @throws Exception thrown if a system level exception occurs. */ + @Override public void prepare() throws Exception { Skill preFetched = (Skill) fetch(getSkillName(), getCurrentSkill()); if (preFetched != null) { @@ -65,6 +65,7 @@ public String getSkillName() { return skillName; } + @StrutsParameter public void setSkillName(String skillName) { this.skillName = skillName; } @@ -73,6 +74,7 @@ protected Dao getDao() { return skillDao; } + @StrutsParameter(depth = 1) public Skill getCurrentSkill() { return currentSkill; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java index 2edf548297..34989dad6f 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain1.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,7 +18,8 @@ */ package org.apache.struts2.showcase.actionchaining; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; public class ActionChain1 extends ActionSupport { @@ -28,6 +27,7 @@ public class ActionChain1 extends ActionSupport { private String actionChain1Property1 = "Property Set In Action Chain 1"; + @Override public String input() throws Exception { return SUCCESS; } @@ -36,6 +36,7 @@ public String getActionChain1Property1() { return actionChain1Property1; } + @StrutsParameter public void setActionChain1Property1(String actionChain1Property1) { this.actionChain1Property1 = actionChain1Property1; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java index 53baf90f52..14196c0a74 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain2.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,7 +18,8 @@ */ package org.apache.struts2.showcase.actionchaining; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; public class ActionChain2 extends ActionSupport { @@ -29,6 +28,7 @@ public class ActionChain2 extends ActionSupport { private String actionChain1Property1; private String actionChain2Property1 = "Property Set in Action Chain 2"; + @Override public String execute() throws Exception { return SUCCESS; } @@ -37,15 +37,16 @@ public String getActionChain1Property1() { return actionChain1Property1; } + @StrutsParameter public void setActionChain1Property1(String actionChain1Property1) { this.actionChain1Property1 = actionChain1Property1; } - public String getActionChain2Property1() { return actionChain2Property1; } + @StrutsParameter public void setActionChain2Property1(String actionChain2Property1) { this.actionChain2Property1 = actionChain2Property1; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java index 43cf103a23..d00d87f479 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/actionchaining/ActionChain3.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,7 +18,8 @@ */ package org.apache.struts2.showcase.actionchaining; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; public class ActionChain3 extends ActionSupport { @@ -30,7 +29,7 @@ public class ActionChain3 extends ActionSupport { private String actionChain2Property1; private String actionChain3Property1 = "Property set in Action Chain 3"; - + @Override public String execute() throws Exception { return SUCCESS; } @@ -39,24 +38,25 @@ public String getActionChain1Property1() { return actionChain1Property1; } + @StrutsParameter public void setActionChain1Property1(String actionChain1Property1) { this.actionChain1Property1 = actionChain1Property1; } - public String getActionChain2Property1() { return actionChain2Property1; } + @StrutsParameter public void setActionChain2Property1(String actionChain2Property1) { this.actionChain2Property1 = actionChain2Property1; } - public String getActionChain3Property1() { return actionChain3Property1; } + @StrutsParameter public void setActionChain3Property1(String actionChain3Property1) { this.actionChain3Property1 = actionChain3Property1; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java index 6fd2bfecbf..ecbf9c0db6 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AjaxTestAction.java @@ -20,11 +20,11 @@ */ package org.apache.struts2.showcase.ajax; -import com.opensymphony.xwork2.Action; +import org.apache.struts2.action.Action; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.io.Serializable; - public class AjaxTestAction implements Action, Serializable { private static int counter = 0; @@ -46,6 +46,7 @@ public String getData() { return data; } + @StrutsParameter public void setData(String data) { this.data = data; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java index 001cffa397..44b7938db8 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/AutocompleterExampleAction.java @@ -20,17 +20,19 @@ */ package org.apache.struts2.showcase.ajax; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.ArrayList; import java.util.List; public class AutocompleterExampleAction extends ActionSupport { private String select; - private List options = new ArrayList(); + private final List options = new ArrayList<>(); private static final long serialVersionUID = -8481638176160014396L; + @Override public String execute() throws Exception { if ("fruits".equals(select)) { options.add("apple"); @@ -49,6 +51,7 @@ public String getSelect() { return select; } + @StrutsParameter public void setSelect(String select) { this.select = select; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java index 10a2d10dbd..f3c9c6420e 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example4ShowPanelAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.ajax; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.text.SimpleDateFormat; import java.util.Date; @@ -51,6 +52,7 @@ public String getGender() { return gender; } + @StrutsParameter public void setGender(String gender) { this.gender = gender; } @@ -59,6 +61,7 @@ public String getName() { return name; } + @StrutsParameter public void setName(String name) { this.name = name; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java index 4f7d3ed656..2873c55924 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/Example5Action.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.ajax; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; public class Example5Action extends ActionSupport { @@ -37,6 +38,7 @@ public String getName() { return name; } + @StrutsParameter public void setName(String name) { this.name = name; } @@ -45,6 +47,7 @@ public Integer getAge() { return age; } + @StrutsParameter public void setAge(Integer age) { this.age = age; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java index 63c34fc4c5..2f05717287 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Category.java @@ -46,8 +46,7 @@ public class Category { new Category(15, "Dojo"), new Category(16, "Prototype"), new Category(17, "Scriptaculous"), - new Category(18, "OpenRico"), - new Category(19, "DWR"))); + new Category(18, "OpenRico"))); } public static Category getById(long id) { diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java index 73362667dc..54b5fded9f 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/GetCategory.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.ajax.tree; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; /** */ @@ -28,6 +29,7 @@ public class GetCategory extends ActionSupport { private long catId; private Category category; + @Override public String execute() throws Exception { if (catId < 1) { // force the root @@ -39,6 +41,7 @@ public String execute() throws Exception { return SUCCESS; } + @StrutsParameter public void setCatId(long catId) { this.catId = catId; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java index 036719157f..a050054b22 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/ajax/tree/Toggle.java @@ -24,6 +24,8 @@ /** */ public class Toggle extends GetCategory { + + @Override public String execute() throws Exception { super.execute(); diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java index 6e60ebfddc..ba16c9a613 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/application/TestDataProvider.java @@ -31,9 +31,10 @@ import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import java.io.Serial; import java.io.Serializable; -import java.util.Arrays; import java.util.Date; +import java.util.List; /** * TestDataProvider. @@ -41,74 +42,76 @@ @Service public class TestDataProvider implements Serializable, InitializingBean { - private static final long serialVersionUID = 1L; - private static final Logger log = LogManager.getLogger(TestDataProvider.class); + @Serial + private static final long serialVersionUID = 1L; + private static final Logger log = LogManager.getLogger(TestDataProvider.class); - public static final String[] POSITIONS = { - "Developer", - "System Architect", - "Sales Manager", - "CEO" - }; + public static final String[] POSITIONS = { + "Developer", + "System Architect", + "Sales Manager", + "CEO" + }; - public static final String[] LEVELS = { - "Junior", - "Senior", - "Master" - }; + public static final String[] LEVELS = { + "Junior", + "Senior", + "Master" + }; - private static final Skill[] TEST_SKILLS = { - new Skill("WW-SEN", "Struts Senior Developer"), - new Skill("WW-JUN", "Struts Junior Developer"), - new Skill("SPRING-DEV", "Spring Developer") - }; + private static final Skill[] TEST_SKILLS = { + new Skill("WW-SEN", "Struts Senior Developer"), + new Skill("WW-JUN", "Struts Junior Developer"), + new Skill("SPRING-DEV", "Spring Developer") + }; - public static final Employee[] TEST_EMPLOYEES = { - new Employee(new Long(1), "Alan", "Smithee", new Date(), new Float(2000f), true, POSITIONS[0], - TEST_SKILLS[0], null, "alan", LEVELS[0], "Nice guy"), - new Employee(new Long(2), "Robert", "Robson", new Date(), new Float(10000f), false, POSITIONS[1], - TEST_SKILLS[1], Arrays.asList(TEST_SKILLS).subList(1, TEST_SKILLS.length), "rob", LEVELS[1], "Smart guy") - }; + public static final Employee[] TEST_EMPLOYEES = { + new Employee(1L, "Alan", "Smithee", new Date(), 2000f, true, POSITIONS[0], + TEST_SKILLS[0], null, "alan", LEVELS[0], "Nice guy"), + new Employee(2L, "Robert", "Robson", new Date(), 10000f, false, POSITIONS[1], + TEST_SKILLS[1], List.of(TEST_SKILLS).subList(1, TEST_SKILLS.length), "rob", LEVELS[1], "Smart guy") + }; - @Autowired - private SkillDao skillDao; + @Autowired + private SkillDao skillDao; - @Autowired - private EmployeeDao employeeDao; + @Autowired + private EmployeeDao employeeDao; - protected void addTestSkills() { - try { - for (int i = 0, j = TEST_SKILLS.length; i < j; i++) { - skillDao.merge(TEST_SKILLS[i]); - } - if (log.isInfoEnabled()) { - log.info("TestDataProvider - [addTestSkills]: Added test skill data."); - } - } catch (StorageException e) { - log.error("TestDataProvider - [addTestSkills]: Exception catched: " + e.getMessage()); - } - } + protected void addTestSkills() { + try { + for (Skill testSkill : TEST_SKILLS) { + skillDao.merge(testSkill); + } + if (log.isInfoEnabled()) { + log.info("TestDataProvider - [addTestSkills]: Added test skill data."); + } + } catch (StorageException e) { + log.error("TestDataProvider - [addTestSkills]: Exception caught: {}", e.getMessage()); + } + } - protected void addTestEmployees() { - try { - for (int i = 0, j = TEST_EMPLOYEES.length; i < j; i++) { - employeeDao.merge(TEST_EMPLOYEES[i]); - } - if (log.isInfoEnabled()) { - log.info("TestDataProvider - [addTestEmployees]: Added test employee data."); - } - } catch (StorageException e) { - log.error("TestDataProvider - [addTestEmployees]: Exception catched: " + e.getMessage()); - } - } + protected void addTestEmployees() { + try { + for (Employee testEmployee : TEST_EMPLOYEES) { + employeeDao.merge(testEmployee); + } + if (log.isInfoEnabled()) { + log.info("TestDataProvider - [addTestEmployees]: Added test employee data."); + } + } catch (StorageException e) { + log.error("TestDataProvider - [addTestEmployees]: Exception caught: {}", e.getMessage()); + } + } - protected void addTestData() { - addTestSkills(); - addTestEmployees(); - } + protected void addTestData() { + addTestSkills(); + addTestEmployees(); + } - public void afterPropertiesSet() throws Exception { - addTestData(); - } + @Override + public void afterPropertiesSet() throws Exception { + addTestData(); + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/async/AsyncFilter.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/async/AsyncFilter.java new file mode 100644 index 0000000000..4ceccb4dd3 --- /dev/null +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/async/AsyncFilter.java @@ -0,0 +1,53 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.showcase.async; + +import jakarta.servlet.Filter; +import jakarta.servlet.FilterChain; +import jakarta.servlet.FilterConfig; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.ServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import java.io.IOException; + +/** + * Filters async actions directly to Struts servlet + */ +public class AsyncFilter implements Filter { + @Override + public void init(FilterConfig filterConfig) throws ServletException { + + } + + @Override + public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { + String requestURI = ((HttpServletRequest) servletRequest).getRequestURI(); + if (!requestURI.contains("/async/receiveNewMessages")) { + filterChain.doFilter(servletRequest, servletResponse); // Just continue chain. + } else { + servletRequest.getRequestDispatcher("/async/receiveNewMessages").forward(servletRequest, servletResponse); + } + } + + @Override + public void destroy() { + + } +} diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/async/ChatRoomAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/async/ChatRoomAction.java new file mode 100644 index 0000000000..bdf7bd4e64 --- /dev/null +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/async/ChatRoomAction.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.struts2.showcase.async; + +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; + +import java.util.ArrayList; +import java.util.List; +import java.util.concurrent.Callable; + +/** + * Example to illustrate the async plugin. + */ +public class ChatRoomAction extends ActionSupport { + private String message; + private Integer lastIndex; + private List newMessages; + + private static final List messages = new ArrayList<>(); + + @StrutsParameter + public void setMessage(String message) { + this.message = message; + } + + @StrutsParameter + public void setLastIndex(Integer lastIndex) { + this.lastIndex = lastIndex; + } + + public List getNewMessages() { + return newMessages; + } + + public Callable receiveNewMessages() throws Exception { + return () -> { + while (lastIndex >= messages.size()) { + Thread.sleep(3000); + } + newMessages = messages.subList(lastIndex, messages.size()); + return SUCCESS; + }; + } + + public String sendMessage() { + synchronized (messages) { + messages.add(message); + } + return SUCCESS; + } +} diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java index fccaad7ce5..fb775075b7 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatAuthenticationInterceptor.java @@ -21,31 +21,32 @@ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.Action; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.interceptor.AbstractInterceptor; -import org.apache.logging.log4j.Logger; +import org.apache.struts2.action.Action; +import org.apache.struts2.ActionContext; +import org.apache.struts2.ActionInvocation; +import org.apache.struts2.interceptor.AbstractInterceptor; import org.apache.logging.log4j.LogManager; -import org.apache.struts2.dispatcher.SessionMap; +import org.apache.logging.log4j.Logger; + +import java.util.Map; public class ChatAuthenticationInterceptor extends AbstractInterceptor { - private static final long serialVersionUID = 1L; - private static final Logger LOG = LogManager.getLogger(ChatAuthenticationInterceptor.class); - public static final String USER_SESSION_KEY = "chatUserSessionKey"; + private static final long serialVersionUID = 1L; + private static final Logger LOG = LogManager.getLogger(ChatAuthenticationInterceptor.class); + public static final String USER_SESSION_KEY = "chatUserSessionKey"; - public String intercept(ActionInvocation invocation) throws Exception { + public String intercept(ActionInvocation invocation) throws Exception { - LOG.debug("Authenticating chat user"); + LOG.debug("Authenticating chat user"); - SessionMap session = (SessionMap) ActionContext.getContext().get(ActionContext.SESSION); - User user = (User) session.get(USER_SESSION_KEY); + Map session = ActionContext.getContext().getSession(); + User user = (User) session.get(USER_SESSION_KEY); - if (user == null) { - return Action.LOGIN; - } - return invocation.invoke(); - } + if (user == null) { + return Action.LOGIN; + } + return invocation.invoke(); + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java index 4497709254..e5b136f34e 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatInterceptor.java @@ -20,35 +20,35 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.Action; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.interceptor.AbstractInterceptor; -import org.apache.logging.log4j.Logger; +import org.apache.struts2.action.Action; +import org.apache.struts2.ActionContext; +import org.apache.struts2.ActionInvocation; +import org.apache.struts2.interceptor.AbstractInterceptor; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; -import javax.servlet.http.HttpSession; +import java.util.Map; /** * Authenticate showcase chat example, make sure everyone have a username. */ public class ChatInterceptor extends AbstractInterceptor { - private static final Logger LOG = LogManager.getLogger(ChatInterceptor.class); + private static final Logger LOG = LogManager.getLogger(ChatInterceptor.class); - private static final long serialVersionUID = 1L; + private static final long serialVersionUID = 1L; - public static final String CHAT_USER_SESSION_KEY = "ChatUserSessionKey"; + public static final String CHAT_USER_SESSION_KEY = "ChatUserSessionKey"; - public String intercept(ActionInvocation invocation) throws Exception { - HttpSession session = (HttpSession) ActionContext.getContext().get(ActionContext.SESSION); - User chatUser = (User) session.getAttribute(CHAT_USER_SESSION_KEY); - if (chatUser == null) { - LOG.debug("Chat user not logged in"); - return Action.LOGIN; - } - return invocation.invoke(); - } + public String intercept(ActionInvocation invocation) throws Exception { + Map session = ActionContext.getContext().getSession(); + User chatUser = (User) session.get(CHAT_USER_SESSION_KEY); + if (chatUser == null) { + LOG.debug("Chat user not logged in"); + return Action.LOGIN; + } + return invocation.invoke(); + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java index a5fc15e738..34ff5788a5 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLoginAction.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.interceptor.SessionAware; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.action.SessionAware; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.Map; @@ -30,7 +31,7 @@ public class ChatLoginAction extends ActionSupport implements SessionAware { private static final long serialVersionUID = 1L; private ChatService chatService; - private Map session; + private Map session; private String name; @@ -42,6 +43,7 @@ public String getName() { return this.name; } + @StrutsParameter public void setName(String name) { this.name = name; } @@ -60,8 +62,8 @@ public String execute() throws Exception { } - // === SessionAware === - public void setSession(Map session) { - this.session = session; - } + @Override + public void withSession(Map session) { + this.session = session; + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java index d0c3e6ba65..03c48087e5 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatLogoutAction.java @@ -20,18 +20,19 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.interceptor.SessionAware; +import org.apache.struts2.ActionSupport; import java.util.Map; +import org.apache.struts2.action.SessionAware; + public class ChatLogoutAction extends ActionSupport implements SessionAware { private static final long serialVersionUID = 1L; private ChatService chatService; - private Map session; + private Map session; public ChatLogoutAction(ChatService chatService) { @@ -50,8 +51,8 @@ public String execute() throws Exception { } - // === SessionAware === - public void setSession(Map session) { - this.session = session; - } + @Override + public void withSession(Map session) { + this.session = session; + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java index 7812cba491..85331ff247 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ChatSessionListener.java @@ -25,9 +25,9 @@ import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.WebApplicationContextUtils; -import javax.servlet.http.HttpSession; -import javax.servlet.http.HttpSessionEvent; -import javax.servlet.http.HttpSessionListener; +import jakarta.servlet.http.HttpSession; +import jakarta.servlet.http.HttpSessionEvent; +import jakarta.servlet.http.HttpSessionListener; public class ChatSessionListener implements HttpSessionListener { diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java index f447b073e7..64af60e912 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/CrudRoomAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; public class CrudRoomAction extends ActionSupport { @@ -36,6 +37,7 @@ public String getDescription() { return description; } + @StrutsParameter public void setDescription(String description) { this.description = description; } @@ -44,6 +46,7 @@ public String getName() { return name; } + @StrutsParameter public void setName(String name) { this.name = name; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java index 5debf9dfb1..0689f3af04 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/DateConverter.java @@ -20,6 +20,8 @@ */ package org.apache.struts2.showcase.chat; +import org.apache.struts2.conversion.impl.XWorkConverter; +import org.apache.struts2.inject.Inject; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.apache.struts2.util.StrutsTypeConverter; @@ -33,6 +35,13 @@ public class DateConverter extends StrutsTypeConverter { private static final Logger LOG = LogManager.getLogger(DateConverter.class); + private XWorkConverter fallbackConverter; + + @Inject + public void setXWorkConverter(XWorkConverter fallbackConverter) { + this.fallbackConverter = fallbackConverter; + } + public Object convertFromString(Map context, String[] values, Class toClass) { if (values.length > 0 && values[0] != null && values[0].trim().length() > 0) { @@ -40,7 +49,8 @@ public Object convertFromString(Map context, String[] values, Class toClass) { try { return sdf.parse(values[0]); } catch (ParseException e) { - LOG.error("error converting value [" + values[0] + "] to Date ", e); + LOG.warn("error converting value [" + values[0] + "] to Date. Trying fallback converter."); + return this.fallbackConverter.convertValue(context, values[0], toClass); } } return null; diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java index 24a54531a8..b25ac7ee8d 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/EnterRoomAction.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.interceptor.SessionAware; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.action.SessionAware; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.Map; @@ -30,13 +31,14 @@ public class EnterRoomAction extends ActionSupport implements SessionAware { private static final long serialVersionUID = 1L; private ChatService chatService; - private Map session; + private Map session; private String roomName; public String getRoomName() { return this.roomName; } + @StrutsParameter public void setRoomName(String roomName) { this.roomName = roomName; } @@ -56,10 +58,9 @@ public String execute() throws Exception { return SUCCESS; } - - // === SessionAware === - public void setSession(Map session) { - this.session = session; - } + @Override + public void withSession(Map session) { + this.session = session; + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java index 592f2d07fe..38009ace37 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/ExitRoomAction.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.interceptor.SessionAware; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.action.SessionAware; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.Map; @@ -31,12 +32,13 @@ public class ExitRoomAction extends ActionSupport implements SessionAware { private String roomName; - private Map session; + private Map session; public String getRoomName() { return roomName; } + @StrutsParameter public void setRoomName(String roomName) { this.roomName = roomName; } @@ -54,9 +56,9 @@ public String execute() throws Exception { return SUCCESS; } - // === SessionAware === - public void setSession(Map session) { - this.session = session; - } + @Override + public void withSession(Map session) { + this.session = session; + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java index a7330e7334..1dad05aa37 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/MessagesAvailableInRoomAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.ArrayList; import java.util.List; @@ -30,13 +31,14 @@ public class MessagesAvailableInRoomAction extends ActionSupport { private static final long serialVersionUID = 1L; private String roomName; - private ChatService chatService; - private List messagesAvailableInRoom = new ArrayList(); + private final ChatService chatService; + private List messagesAvailableInRoom = new ArrayList<>(); public String getRoomName() { return this.roomName; } + @StrutsParameter public void setRoomName(String roomName) { this.roomName = roomName; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java index 8ed8b4e825..f511c0bf4e 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/RoomsAvailableAction.java @@ -20,7 +20,7 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; import java.util.ArrayList; import java.util.List; diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java index 69a66609c6..b179f94940 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/SendMessageToRoomAction.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.interceptor.SessionAware; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.action.SessionAware; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.Map; @@ -29,11 +30,11 @@ public class SendMessageToRoomAction extends ActionSupport implements SessionAwa private static final long serialVersionUID = 1L; - private ChatService chatService; + private final ChatService chatService; private String roomName; private String message; - private Map session; + private Map session; public SendMessageToRoomAction(ChatService chatService) { @@ -44,6 +45,7 @@ public String getRoomName() { return this.roomName; } + @StrutsParameter public void setRoomName(String roomName) { this.roomName = roomName; } @@ -52,11 +54,12 @@ public String getMessage() { return this.message; } + @StrutsParameter public void setMessage(String message) { this.message = message; } - + @Override public String execute() throws Exception { User user = (User) session.get(ChatAuthenticationInterceptor.USER_SESSION_KEY); try { @@ -67,9 +70,10 @@ public String execute() throws Exception { return SUCCESS; } - public void setSession(Map session) { - this.session = session; - } + @Override + public void withSession(Map session) { + this.session = session; + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java index c2a15c1072..e0d61b4363 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableAction.java @@ -20,7 +20,7 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; import java.util.ArrayList; import java.util.List; diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java index bebd738307..4cf1acaec9 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/chat/UsersAvailableInRoomAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.chat; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.ArrayList; import java.util.List; @@ -29,8 +30,8 @@ public class UsersAvailableInRoomAction extends ActionSupport { private static final long serialVersionUID = 1L; - private ChatService chatService; - private List usersAvailableInRoom = new ArrayList(); + private final ChatService chatService; + private List usersAvailableInRoom = new ArrayList<>(); private String roomName; @@ -43,6 +44,7 @@ public String getRoomName() { return this.roomName; } + @StrutsParameter public void setRoomName(String roomName) { this.roomName = roomName; } @@ -51,6 +53,7 @@ public List getUsersAvailableInRoom() { return usersAvailableInRoom; } + @Override public String execute() throws Exception { try { usersAvailableInRoom = chatService.getUsersAvailableInRoom(roomName); diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java index 66e9c27467..d0eb196b4e 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/AddressAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.conversion; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.LinkedHashSet; import java.util.Set; @@ -30,7 +31,7 @@ */ public class AddressAction extends ActionSupport { - private Set
addresses = new LinkedHashSet
(); + private Set
addresses = new LinkedHashSet<>(); public String input() throws Exception { return SUCCESS; @@ -41,6 +42,7 @@ public String submit() throws Exception { return SUCCESS; } + @StrutsParameter(depth = 2) public Set
getAddresses() { return addresses; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java index a8f8cd624b..17d7cbe28c 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/OperationsEnumAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.conversion; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.Arrays; import java.util.LinkedList; @@ -33,7 +34,7 @@ public class OperationsEnumAction extends ActionSupport { private static final long serialVersionUID = -2229489704988870318L; - private List selectedOperations = new LinkedList(); + private List selectedOperations = new LinkedList<>(); public String input() throws Exception { return SUCCESS; @@ -47,11 +48,11 @@ public List getSelectedOperations() { return this.selectedOperations; } + @StrutsParameter public void setSelectedOperations(List selectedOperations) { this.selectedOperations = selectedOperations; } - public List getAvailableOperations() { return Arrays.asList(OperationsEnum.values()); } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java index 70307db80e..1f7cd4d29f 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/conversion/PersonAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.conversion; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.List; @@ -36,6 +37,7 @@ public String submit() throws Exception { return SUCCESS; } + @StrutsParameter(depth = 2) public List getPersons() { return persons; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java index c9fab7f468..4c667b644a 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/filedownload/FileDownloadAction.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.filedownload; -import com.opensymphony.xwork2.Action; +import org.apache.struts2.action.Action; import org.apache.struts2.ServletActionContext; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.io.InputStream; @@ -38,6 +39,7 @@ public String execute() throws Exception { return SUCCESS; } + @StrutsParameter public void setInputPath(String value) { inputPath = sanitizeInputPath(value); } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java index 60053067e3..1fa4eab527 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/FileUploadAction.java @@ -20,68 +20,76 @@ */ package org.apache.struts2.showcase.fileupload; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.action.UploadedFilesAware; +import org.apache.struts2.dispatcher.multipart.UploadedFile; +import org.apache.struts2.interceptor.parameter.StrutsParameter; -import java.io.File; +import java.util.List; /** * Show case File Upload example's action. FileUploadAction */ -public class FileUploadAction extends ActionSupport { - - private static final long serialVersionUID = 5156288255337069381L; - - private String contentType; - private File upload; - private String fileName; - private String caption; - - public String input() throws Exception { - return SUCCESS; - } - - public String upload() throws Exception { - return SUCCESS; - } - - // since we are using the file name will be - // obtained through getter/setter of FileName - public String getUploadFileName() { - return fileName; - } - - public void setUploadFileName(String fileName) { - this.fileName = fileName; - } - - - // since we are using the content type will be - // obtained through getter/setter of ContentType - public String getUploadContentType() { - return contentType; - } - - public void setUploadContentType(String contentType) { - this.contentType = contentType; - } - - - // since we are using the File itself will be - // obtained through getter/setter of - public File getUpload() { - return upload; - } - - public void setUpload(File upload) { - this.upload = upload; - } - - - public String getCaption() { - return caption; - } - - public void setCaption(String caption) { - this.caption = caption; - } +public class FileUploadAction extends ActionSupport implements UploadedFilesAware { + + private String contentType; + private UploadedFile uploadedFile; + private String fileName; + private String caption; + private String originalName; + private String inputName; + + public String input() throws Exception { + return SUCCESS; + } + + public String upload() throws Exception { + return SUCCESS; + } + + public String getContentType() { + return contentType; + } + + public String getFileName() { + return fileName; + } + + public String getOriginalName() { + return originalName; + } + + public String getInputName() { + return inputName; + } + + public Object getUploadedFile() { + return uploadedFile.getContent(); + } + + public String getCaption() { + return caption; + } + + @StrutsParameter + public void setCaption(String caption) { + this.caption = caption; + } + + public long getUploadSize() { + if (uploadedFile != null) { + return uploadedFile.length(); + } else { + return 0; + } + } + + @Override + public void withUploadedFiles(List uploadedFiles) { + this.uploadedFile = uploadedFiles.get(0); + this.fileName = uploadedFile.getName(); + this.contentType = uploadedFile.getContentType(); + this.originalName = uploadedFile.getOriginalName(); + this.inputName = uploadedFile.getInputName(); + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java index b1a598543d..8b7c630be6 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingArrayAction.java @@ -21,62 +21,56 @@ // START SNIPPET: entire-file package org.apache.struts2.showcase.fileupload; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.action.UploadedFilesAware; +import org.apache.struts2.dispatcher.multipart.UploadedFile; -import java.io.File; +import java.util.List; /** - * Showcase action - mutiple file upload using array. - * - * @version $Date$ $Id$ + * Showcase action - multiple file upload using array. */ -public class MultipleFileUploadUsingArrayAction extends ActionSupport { - - private File[] uploads; - private String[] uploadFileNames; - private String[] uploadContentTypes; - +public class MultipleFileUploadUsingArrayAction extends ActionSupport implements UploadedFilesAware { - public String upload() throws Exception { - System.out.println("\n\n upload2"); - System.out.println("files:"); - for (File u : uploads) { - System.out.println("*** " + u + "\t" + u.length()); - } - System.out.println("filenames:"); - for (String n : uploadFileNames) { - System.out.println("*** " + n); - } - System.out.println("content types:"); - for (String c : uploadContentTypes) { - System.out.println("*** " + c); - } - System.out.println("\n\n"); - return SUCCESS; - } + private List uploadedFiles; - public File[] getUpload() { - return this.uploads; - } + public List getUpload() { + return this.uploadedFiles; + } - public void setUpload(File[] upload) { - this.uploads = upload; - } + public String upload() throws Exception { + System.out.println("\n\n upload2"); + System.out.println("files:"); + for (UploadedFile u : uploadedFiles) { + System.out.println("*** " + u + "\t" + u.length()); + } + System.out.println("filenames:"); + for (String n : getUploadFileNames()) { + System.out.println("*** " + n); + } + System.out.println("content types:"); + for (String c : getUploadContentTypes()) { + System.out.println("*** " + c); + } + System.out.println("\n\n"); + return SUCCESS; + } - public String[] getUploadFileName() { - return this.uploadFileNames; - } + @Override + public void withUploadedFiles(List uploadedFiles) { + this.uploadedFiles = uploadedFiles; + } - public void setUploadFileName(String[] uploadFileName) { - this.uploadFileNames = uploadFileName; - } + private String[] getUploadFileNames() { + return this.uploadedFiles.stream() + .map(UploadedFile::getOriginalName) + .toArray(String[]::new); + } - public String[] getUploadContentType() { - return this.uploadContentTypes; - } + private String[] getUploadContentTypes() { + return this.uploadedFiles.stream() + .map(UploadedFile::getContentType) + .toArray(String[]::new); + } - public void setUploadContentType(String[] uploadContentType) { - this.uploadContentTypes = uploadContentType; - } } -// END SNIPPET: entire-file \ No newline at end of file diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java index 7b4325e987..f32e643dec 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction.java @@ -21,65 +21,57 @@ // START SNIPPET: entire-file package org.apache.struts2.showcase.fileupload; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.action.UploadedFilesAware; +import org.apache.struts2.dispatcher.multipart.UploadedFile; -import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; /** * Showcase action - multiple file upload using List - * - * @version $Date$ $Id$ */ -public class MultipleFileUploadUsingListAction extends ActionSupport { - - private List uploads = new ArrayList<>(); - private List uploadFileNames = new ArrayList<>(); - private List uploadContentTypes = new ArrayList<>(); - - - public List getUpload() { - return this.uploads; - } - - public void setUpload(List uploads) { - this.uploads = uploads; - } +public class MultipleFileUploadUsingListAction extends ActionSupport implements UploadedFilesAware { - public List getUploadFileName() { - return this.uploadFileNames; - } + private List uploads = new ArrayList<>(); - public void setUploadFileName(List uploadFileNames) { - this.uploadFileNames = uploadFileNames; - } + public List getUpload() { + return this.uploads; + } - public List getUploadContentType() { - return this.uploadContentTypes; - } + @Override + public void withUploadedFiles(List uploads) { + this.uploads = uploads; + } - public void setUploadContentType(List contentTypes) { - this.uploadContentTypes = contentTypes; - } + private List getUploadFileNames() { + return this.uploads.stream() + .map(UploadedFile::getOriginalName) + .collect(Collectors.toList()); + } - public String upload() throws Exception { + private List getUploadContentTypes() { + return this.uploads.stream() + .map(UploadedFile::getContentType) + .collect(Collectors.toList()); + } - System.out.println("\n\n upload1"); - System.out.println("files:"); - for (File u : uploads) { - System.out.println("*** " + u + "\t" + u.length()); - } - System.out.println("filenames:"); - for (String n : uploadFileNames) { - System.out.println("*** " + n); - } - System.out.println("content types:"); - for (String c : uploadContentTypes) { - System.out.println("*** " + c); - } - System.out.println("\n\n"); - return SUCCESS; - } -} -// END SNIPPET: entire-file \ No newline at end of file + public String upload() throws Exception { + System.out.println("\n\n upload1"); + System.out.println("files:"); + for (UploadedFile u : uploads) { + System.out.println("*** " + u + "\t" + u.length()); + } + System.out.println("filenames:"); + for (String n : getUploadFileNames()) { + System.out.println("*** " + n); + } + System.out.println("content types:"); + for (String c : getUploadContentTypes()) { + System.out.println("*** " + c); + } + System.out.println("\n\n"); + return SUCCESS; + } +} \ No newline at end of file diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java index 5cf6b49251..45c58ab055 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/CustomFreemarkerManager.java @@ -20,12 +20,12 @@ */ package org.apache.struts2.showcase.freemarker; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.struts2.views.freemarker.FreemarkerManager; import org.apache.struts2.views.freemarker.ScopesHashModel; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** *

diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java index c23ee156a7..36831c7800 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/freemarker/StandardTagsAction.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.freemarker; -import com.opensymphony.xwork2.ActionSupport; -import com.opensymphony.xwork2.Preparable; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.Preparable; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.text.DateFormatSymbols; @@ -34,6 +35,7 @@ public class StandardTagsAction extends ActionSupport implements Preparable { private String[] gender; private String[] months; + @Override public void prepare() { months = new DateFormatSymbols().getMonths(); name = StandardTagsAction.class.getName().substring(StandardTagsAction.class.getName().lastIndexOf(".") + 1); @@ -44,6 +46,7 @@ public String getName() { return name; } + @StrutsParameter public void setName(String name) { this.name = name; } @@ -52,15 +55,16 @@ public String[] getMonths() { return months; } + @StrutsParameter public void setMonths(String[] months) { this.months = months; } - public String[] getGender() { return gender; } + @StrutsParameter public void setGender(String[] gender) { this.gender = gender; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java index 24b777355e..83946bdff2 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GetUpdatedHangmanAction.java @@ -20,16 +20,17 @@ */ package org.apache.struts2.showcase.hangman; -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.interceptor.SessionAware; +import org.apache.struts2.ActionSupport; import java.util.Map; +import org.apache.struts2.action.SessionAware; + public class GetUpdatedHangmanAction extends ActionSupport implements SessionAware { private static final long serialVersionUID = 5506025785406043027L; - private Map session; + private Map session; private Hangman hangman; @@ -45,10 +46,6 @@ public String execute() throws Exception { return SUCCESS; } - public void setSession(Map session) { - this.session = session; - } - public Hangman getHangman() { return hangman; } @@ -56,4 +53,9 @@ public Hangman getHangman() { public void setHangman(Hangman hangman) { this.hangman = hangman; } + + @Override + public void withSession(Map session) { + this.session = session; + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java index 40ab60fe4e..c823eabbc4 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/GuessCharacterAction.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.hangman; -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.interceptor.SessionAware; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.action.SessionAware; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.Map; @@ -29,10 +30,11 @@ public class GuessCharacterAction extends ActionSupport implements SessionAware private static final long serialVersionUID = 9050915577007590674L; - private Map session; + private Map session; private Character character; private Hangman hangman; + @Override public String execute() throws Exception { hangman = (Hangman) session.get(HangmanConstants.HANGMAN_SESSION_KEY); hangman.guess(character); @@ -44,10 +46,7 @@ public Hangman getHangman() { return hangman; } - public void setSession(Map session) { - this.session = session; - } - + @StrutsParameter public void setCharacter(Character character) { this.character = character; } @@ -55,4 +54,9 @@ public void setCharacter(Character character) { public Character getCharacter() { return this.character; } + + @Override + public void withSession(Map session) { + this.session = session; + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java index 4dce5521cd..dc21c91b4d 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Hangman.java @@ -20,40 +20,34 @@ */ package org.apache.struts2.showcase.hangman; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +import java.io.Serial; import java.io.Serializable; import java.util.ArrayList; -import java.util.Arrays; import java.util.List; public class Hangman implements Serializable { + private static final Logger log = LogManager.getLogger(Hangman.class); + + @Serial private static final long serialVersionUID = 8566954355839652509L; - private Vocab vocab; + private final Vocab vocab; private Boolean win = false; private int guessLeft = 5; - public List charactersAvailable; + public final List charactersAvailable; public List charactersGuessed; public Hangman(Vocab vocab) { - // Arrays.asList(...) returns List that doesn't support remove(), hence - // we wrap it with an ArrayList to avoid UnsupportedOperationException - // when doing a remove() - charactersAvailable = new ArrayList(Arrays.asList( - new Character[]{ - Character.valueOf('A'), Character.valueOf('B'), Character.valueOf('C'), - Character.valueOf('D'), Character.valueOf('E'), Character.valueOf('F'), - Character.valueOf('G'), Character.valueOf('H'), Character.valueOf('I'), - Character.valueOf('J'), Character.valueOf('K'), Character.valueOf('L'), - Character.valueOf('M'), Character.valueOf('N'), Character.valueOf('O'), - Character.valueOf('P'), Character.valueOf('Q'), Character.valueOf('R'), - Character.valueOf('S'), Character.valueOf('T'), Character.valueOf('U'), - Character.valueOf('V'), Character.valueOf('W'), Character.valueOf('X'), - Character.valueOf('Y'), Character.valueOf('Z') - })); - charactersGuessed = new ArrayList(); + charactersAvailable = new ArrayList<>(List.of( + 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', + 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z')); + charactersGuessed = new ArrayList<>(); this.vocab = vocab; } @@ -75,8 +69,8 @@ public void guess(Character character) { } if (vocab.containsAllCharacter(charactersGuessed)) { win = true; + log.info("Game won"); } - System.out.println(" *********************************** " + win); } } @@ -98,7 +92,7 @@ public Integer guessLeft() { public List getCharactersAvailable() { synchronized (charactersAvailable) { - return new ArrayList(charactersAvailable); + return new ArrayList<>(charactersAvailable); //return charactersAvailable; } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java index a38b10954e..fe9f2333df 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/StartHangmanAction.java @@ -20,11 +20,12 @@ */ package org.apache.struts2.showcase.hangman; -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.interceptor.SessionAware; +import org.apache.struts2.ActionSupport; import java.util.Map; +import org.apache.struts2.action.SessionAware; + import static org.apache.struts2.showcase.hangman.HangmanConstants.HANGMAN_SESSION_KEY; public class StartHangmanAction extends ActionSupport implements SessionAware { @@ -33,7 +34,7 @@ public class StartHangmanAction extends ActionSupport implements SessionAware { private HangmanService service; private Hangman hangman; - private Map session; + private Map session; public StartHangmanAction(HangmanService service) { @@ -53,8 +54,8 @@ public Hangman getHangman() { } - // === SessionAware === - public void setSession(Map session) { - this.session = session; - } + @Override + public void withSession(Map session) { + this.session = session; + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java index 80f8b470d1..3be7bc72c4 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/hangman/Vocab.java @@ -20,17 +20,19 @@ */ package org.apache.struts2.showcase.hangman; +import java.io.Serial; import java.io.Serializable; -import java.util.ArrayList; import java.util.Arrays; +import java.util.HashSet; import java.util.List; public class Vocab implements Serializable { + @Serial private static final long serialVersionUID = 1L; - private String vocab; - private String hint; + private final String vocab; + private final String hint; private Character[] characters; // character this vocab is made up of public Vocab(String vocab, String hint) { @@ -52,7 +54,7 @@ public String getHint() { public Boolean containCharacter(Character character) { assert (character != null); - return (vocab.contains(character.toString())) ? true : false; + return vocab.contains(character.toString()); } public Character[] inCharacters() { @@ -60,32 +62,21 @@ public Character[] inCharacters() { char[] c = vocab.toCharArray(); characters = new Character[c.length]; for (int a = 0; a < c.length; a++) { - characters[a] = Character.valueOf(c[a]); + characters[a] = c[a]; } } return characters; } public boolean containsAllCharacter(List charactersGuessed) { - Character[] chars = inCharacters(); - List tmpChars = Arrays.asList(chars); - return charactersGuessed.containsAll(tmpChars); + return new HashSet<>(charactersGuessed).containsAll(Arrays.asList(inCharacters())); } - public static void main(String args[]) throws Exception { + public static void main(String[] args) throws Exception { Vocab v = new Vocab("JAVA", "a java word"); - List list1 = new ArrayList(); - list1.add(new Character('J')); - list1.add(new Character('V')); - - List list2 = new ArrayList(); - list2.add(new Character('J')); - list2.add(new Character('V')); - list2.add(new Character('A')); - - System.out.println(v.containsAllCharacter(list1)); - System.out.println(v.containsAllCharacter(list2)); + System.out.println(v.containsAllCharacter(List.of('J', 'V'))); + System.out.println(v.containsAllCharacter(List.of('J', 'V', 'A'))); } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/model/MyDto.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/model/MyDto.java new file mode 100644 index 0000000000..7abee847e7 --- /dev/null +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/model/MyDto.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.showcase.model; + +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; + +import static java.util.Collections.singletonMap; + +public class MyDto { + + public String str = "no"; + + public Map map = new HashMap<>(singletonMap("key", "no")); + public int[] array = new int[]{0}; + + @Override + public String toString() { + return "str=" + str + ", map=" + map + ", array=" + Arrays.toString(array); + } +} diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java index 3dd5bde49f..740644d8bc 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/model/Skill.java @@ -20,7 +20,7 @@ */ package org.apache.struts2.showcase.model; -import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.commons.text.StringEscapeUtils; import java.io.Serializable; diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java index c32cd20031..9dd0454e59 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/ModelDrivenAction.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.modelDriven; -import com.opensymphony.xwork2.ActionSupport; -import com.opensymphony.xwork2.ModelDriven; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.ModelDriven; +import org.apache.struts2.showcase.modelDriven.model.Gangster; /** * Action to demonstrate simple model-driven feature of the framework. @@ -30,15 +31,18 @@ public class ModelDrivenAction extends ActionSupport implements ModelDriven { private static final long serialVersionUID = 1271130427666936592L; + @Override public String input() throws Exception { return SUCCESS; } + @Override public String execute() throws Exception { return SUCCESS; } - public Object getModel() { + @Override + public Gangster getModel() { return new Gangster(); } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/Gangster.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/model/Gangster.java similarity index 96% rename from apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/Gangster.java rename to apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/model/Gangster.java index be2a571bb5..6d0b263662 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/Gangster.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/modelDriven/model/Gangster.java @@ -18,7 +18,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.struts2.showcase.modelDriven; +package org.apache.struts2.showcase.modelDriven.model; import java.io.Serializable; diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java index 4d102f7806..3e52dbf028 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java @@ -20,13 +20,13 @@ */ package org.apache.struts2.showcase.person; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import org.springframework.beans.factory.annotation.Autowired; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; /** @@ -42,13 +42,14 @@ public class EditPersonAction extends ActionSupport { @Autowired private PersonManager personManager; - private List persons = new ArrayList(); + private List persons = new ArrayList<>(); /** * A default implementation that does nothing an returns "success". * * @return {@link #INPUT} */ + @Override public String execute() throws Exception { persons.addAll(personManager.getPeople()); return INPUT; @@ -68,6 +69,7 @@ public String save() throws Exception { return "list"; } + @StrutsParameter(depth = 2) public List getPersons() { return persons; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java index e64c199d60..34e5d2f3cd 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java @@ -20,7 +20,7 @@ */ package org.apache.struts2.showcase.person; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; import org.apache.struts2.convention.annotation.Result; import org.springframework.beans.factory.annotation.Autowired; @@ -35,8 +35,9 @@ public class ListPeopleAction extends ActionSupport { @Autowired private PersonManager personManager; - private List people = new ArrayList(); + private final List people = new ArrayList<>(); + @Override public String execute() { people.addAll(personManager.getPeople()); diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java index eb07bd721c..71054aa109 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java @@ -20,9 +20,10 @@ */ package org.apache.struts2.showcase.person; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; import org.apache.struts2.convention.annotation.Result; import org.apache.struts2.convention.annotation.Results; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import org.springframework.beans.factory.annotation.Autowired; @@ -38,12 +39,14 @@ public class NewPersonAction extends ActionSupport { private PersonManager personManager; private Person person; + @Override public String execute() { personManager.createPerson(person); return "list"; } + @StrutsParameter(depth = 1) public Person getPerson() { return person; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/person/package-info.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/person/package-info.java index c21b7a84d5..ae66590618 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/person/package-info.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/person/package-info.java @@ -1,3 +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. + */ @ParentPackage("person") @Namespace("/person") package org.apache.struts2.showcase.person; diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/servlet/TestServlet.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/servlet/TestServlet.java new file mode 100644 index 0000000000..26f82f6fe8 --- /dev/null +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/servlet/TestServlet.java @@ -0,0 +1,41 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.showcase.servlet; + +import jakarta.servlet.ServletException; +import jakarta.servlet.http.HttpServlet; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.IOException; + +public class TestServlet extends HttpServlet { + @Override + public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException { + switch (request.getPathInfo()) { + case "/forward": + getServletContext().getRequestDispatcher("/dispatcher/dispatch.action").forward(request, response); + break; + default: + response.sendError(404); + break; + } + } +} diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java index 3b71fa68ec..2cd4b5a1b2 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/source/ViewSourceAction.java @@ -20,17 +20,16 @@ */ package org.apache.struts2.showcase.source; -import com.opensymphony.xwork2.ActionSupport; -import com.opensymphony.xwork2.util.ClassLoaderUtil; -import org.apache.struts2.ServletActionContext; -import org.apache.struts2.util.ServletContextAware; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.util.ClassLoaderUtil; +import org.apache.struts2.action.ServletContextAware; +import org.apache.struts2.interceptor.parameter.StrutsParameter; -import javax.servlet.ServletContext; +import jakarta.servlet.ServletContext; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStream; import java.io.InputStreamReader; -import java.net.MalformedURLException; import java.net.URL; import java.util.ArrayList; import java.util.List; @@ -41,195 +40,197 @@ */ public class ViewSourceAction extends ActionSupport implements ServletContextAware { - private String page; - private String className; - private String config; - - private List pageLines; - private List classLines; - private List configLines; - - private int configLine; - private int padding = 10; - - private ServletContext servletContext; - - public String execute() throws MalformedURLException, IOException { - - if (page != null) { - - InputStream in = ClassLoaderUtil.getResourceAsStream(page.substring(page.indexOf("//") + 1), getClass()); - page = page.replace("//", "/"); - - if (in == null) { - in = servletContext.getResourceAsStream(page); - while (in == null && page.indexOf('/', 1) > 0) { - page = page.substring(page.indexOf('/', 1)); - in = servletContext.getResourceAsStream(page); - } - } - pageLines = read(in, -1); - - if (in != null) { - in.close(); - } - } - - if (className != null) { - className = "/" + className.replace('.', '/') + ".java"; - InputStream in = getClass().getResourceAsStream(className); - if (in == null) { - in = servletContext.getResourceAsStream("/WEB-INF/src" + className); - } - classLines = read(in, -1); - - if (in != null) { - in.close(); - } - } - - String rootPath = ServletActionContext.getServletContext().getRealPath("/"); - - if (config != null && (rootPath == null || config.startsWith(rootPath))) { - int pos = config.lastIndexOf(':'); - configLine = Integer.parseInt(config.substring(pos + 1)); - config = config.substring(0, pos).replace("//", "/"); - configLines = read(new URL(config).openStream(), configLine); - } - return SUCCESS; - } - - - /** - * @param className the className to set - */ - public void setClassName(String className) { - if (className != null && className.trim().length() > 0) { - this.className = className; - } - } - - /** - * @param config the config to set - */ - public void setConfig(String config) { - if (config != null && config.trim().length() > 0) { - this.config = config; - } - } - - /** - * @param page the page to set - */ - public void setPage(String page) { - if (page != null && page.trim().length() > 0) { - this.page = page; - } - } - - /** - * @param padding the padding to set - */ - public void setPadding(int padding) { - this.padding = padding; - } - - - /** - * @return the classLines - */ - public List getClassLines() { - return classLines; - } - - /** - * @return the configLines - */ - public List getConfigLines() { - return configLines; - } - - /** - * @return the pageLines - */ - public List getPageLines() { - return pageLines; - } - - /** - * @return the className - */ - public String getClassName() { - return className; - } - - /** - * @return the config - */ - public String getConfig() { - return config; - } - - /** - * @return the page - */ - public String getPage() { - return page; - } - - /** - * @return the configLine - */ - public int getConfigLine() { - return configLine; - } - - /** - * @return the padding - */ - public int getPadding() { - return padding; - } - - /** - * Reads in a strea, optionally only including the target line number - * and its padding - * - * @param in The input stream - * @param targetLineNumber The target line number, negative to read all - * @return A list of lines - */ - private List read(InputStream in, int targetLineNumber) { - List snippet = null; - if (in != null) { - snippet = new ArrayList(); - int startLine = 0; - int endLine = Integer.MAX_VALUE; - if (targetLineNumber > 0) { - startLine = targetLineNumber - padding; - endLine = targetLineNumber + padding; - } - try { - BufferedReader reader = new BufferedReader(new InputStreamReader(in)); - - int lineno = 0; - String line; - while ((line = reader.readLine()) != null) { - lineno++; - if (lineno >= startLine && lineno <= endLine) { - snippet.add(line); - } - } - } catch (Exception ex) { - // ignoring as snippet not available isn't a big deal - } - } - return snippet; - } - - public void setServletContext(ServletContext arg0) { - this.servletContext = arg0; - } + private String page; + private String className; + private String config; + + private List pageLines; + private List classLines; + private List configLines; + + private int configLine; + private int padding = 10; + + private ServletContext servletContext; + + public String execute() throws IOException { + + if (page != null) { + + InputStream in = ClassLoaderUtil.getResourceAsStream(page.substring(page.indexOf("//") + 1), getClass()); + page = page.replace("//", "/"); + + if (in == null) { + in = servletContext.getResourceAsStream(page); + while (in == null && page.indexOf('/', 1) > 0) { + page = page.substring(page.indexOf('/', 1)); + in = servletContext.getResourceAsStream(page); + } + } + pageLines = read(in, -1); + + if (in != null) { + in.close(); + } + } + + if (className != null) { + className = "/" + className.replace('.', '/') + ".java"; + InputStream in = getClass().getResourceAsStream(className); + if (in == null) { + in = servletContext.getResourceAsStream("/WEB-INF/src/java" + className); + } + classLines = read(in, -1); + + if (in != null) { + in.close(); + } + } + + if (config != null && config.startsWith("file:/")) { + int pos = config.lastIndexOf(':'); + configLine = Integer.parseInt(config.substring(pos + 1)); + configLines = read(new URL(config.substring(0, pos)).openStream(), configLine); + } + return SUCCESS; + } + + + /** + * @param className the className to set + */ + @StrutsParameter + public void setClassName(String className) { + if (className != null && !className.trim().isEmpty()) { + this.className = className; + } + } + + /** + * @param config the config to set + */ + @StrutsParameter + public void setConfig(String config) { + if (config != null && !config.trim().isEmpty()) { + this.config = config; + } + } + + /** + * @param page the page to set + */ + @StrutsParameter + public void setPage(String page) { + if (page != null && !page.trim().isEmpty()) { + this.page = page; + } + } + + /** + * @param padding the padding to set + */ + @StrutsParameter + public void setPadding(int padding) { + this.padding = padding; + } + + + /** + * @return the classLines + */ + public List getClassLines() { + return classLines; + } + + /** + * @return the configLines + */ + public List getConfigLines() { + return configLines; + } + + /** + * @return the pageLines + */ + public List getPageLines() { + return pageLines; + } + + /** + * @return the className + */ + public String getClassName() { + return className; + } + + /** + * @return the config + */ + public String getConfig() { + return config; + } + + /** + * @return the page + */ + public String getPage() { + return page; + } + + /** + * @return the configLine + */ + public int getConfigLine() { + return configLine; + } + + /** + * @return the padding + */ + public int getPadding() { + return padding; + } + + /** + * Reads in a stream, optionally only including the target line number + * and its padding + * + * @param in The input stream + * @param targetLineNumber The target line number, negative to read all + * @return A list of lines + */ + private List read(InputStream in, int targetLineNumber) { + List snippet = null; + if (in != null) { + snippet = new ArrayList<>(); + int startLine = 0; + int endLine = Integer.MAX_VALUE; + if (targetLineNumber > 0) { + startLine = targetLineNumber - padding; + endLine = targetLineNumber + padding; + } + try { + BufferedReader reader = new BufferedReader(new InputStreamReader(in)); + + int lineno = 0; + String line; + while ((line = reader.readLine()) != null) { + lineno++; + if (lineno >= startLine && lineno <= endLine) { + snippet.add(line); + } + } + } catch (Exception ex) { + // ignoring as snippet not available isn't a big deal + } + } + return snippet; + } + + @Override + public void withServletContext(ServletContext arg0) { + this.servletContext = arg0; + } } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java index 7ae6257eb0..176e9449bb 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actionPrefix/SubmitAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.tag.nonui.actionPrefix; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; public class SubmitAction extends ActionSupport { @@ -32,10 +33,12 @@ public String getText() { return text; } + @StrutsParameter public void setText(String text) { this.text = text; } + @Override public String execute() throws Exception { return SUCCESS; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java index d39f877a2b..e105449edf 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/actiontag/ActionTagDemo.java @@ -20,7 +20,7 @@ */ package org.apache.struts2.showcase.tag.nonui.actiontag; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; /** */ diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/debugtag/DebugTagAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/debugtag/DebugTagAction.java new file mode 100644 index 0000000000..be740d506a --- /dev/null +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/debugtag/DebugTagAction.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.struts2.showcase.tag.nonui.debugtag; + +import org.apache.struts2.ActionSupport; +import org.apache.struts2.dispatcher.PrepareOperations; + +public class DebugTagAction extends ActionSupport { + + @Override + public String execute() throws Exception { + PrepareOperations.overrideDevMode(true); // Just for Showcase, explicitly switch on for this action only + return SUCCESS; + } +} diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java index f3936a49b7..ada4ccb686 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/AppendIteratorTagDemo.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.tag.nonui.iteratortag; -import com.opensymphony.xwork2.ActionSupport; -import com.opensymphony.xwork2.Validateable; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.Validateable; +import org.apache.struts2.interceptor.parameter.StrutsParameter; /** * @@ -47,25 +48,25 @@ public void validate() { } } - public String getIteratorValue1() { return iteratorValue1; } + @StrutsParameter public void setIteratorValue1(String iteratorValue1) { this.iteratorValue1 = iteratorValue1; } - public String getIteratorValue2() { return iteratorValue2; } + @StrutsParameter public void setIteratorValue2(String iteratorValue2) { this.iteratorValue2 = iteratorValue2; } - + @Override public String input() throws Exception { return SUCCESS; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java index 0e48519bdb..735c38fd6f 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.tag.nonui.iteratortag; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; /** */ @@ -37,34 +38,34 @@ public String getValue() { return value; } + @StrutsParameter public void setValue(String value) { this.value = value; } - public Integer getCount() { return count; } + @StrutsParameter public void setCount(Integer count) { this.count = count; } - public String getSeparator() { return this.separator; } + @StrutsParameter public void setSeparator(String separator) { this.separator = separator; } - public String submit() throws Exception { return SUCCESS; } - + @Override public String input() throws Exception { return SUCCESS; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java index cc8fa28dea..33c5cdd59f 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/MergeIteratorTagDemo.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.tag.nonui.iteratortag; -import com.opensymphony.xwork2.ActionSupport; -import com.opensymphony.xwork2.Validateable; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.Validateable; +import org.apache.struts2.interceptor.parameter.StrutsParameter; /** @@ -33,7 +34,7 @@ public class MergeIteratorTagDemo extends ActionSupport implements Validateable private String iteratorValue1; private String iteratorValue2; - + @Override public void validate() { if (iteratorValue1 == null || iteratorValue1.trim().length() <= 0) { addFieldError("iteratorValue1", "iterator value 1 cannot be empty"); @@ -47,25 +48,25 @@ public void validate() { } } - public String getIteratorValue1() { return this.iteratorValue1; } + @StrutsParameter public void setIteratorValue1(String iteratorValue1) { this.iteratorValue1 = iteratorValue1; } - public String getIteratorValue2() { return this.iteratorValue2; } + @StrutsParameter public void setIteratorValue2(String iteratorValue2) { this.iteratorValue2 = iteratorValue2; } - + @Override public String input() throws Exception { return SUCCESS; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java index 11b2211374..3d5567abe1 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/tag/nonui/iteratortag/SubsetIteratorTagDemo.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.tag.nonui.iteratortag; -import com.opensymphony.xwork2.ActionSupport; -import com.opensymphony.xwork2.Validateable; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.Validateable; +import org.apache.struts2.interceptor.parameter.StrutsParameter; /** * @@ -34,7 +35,7 @@ public class SubsetIteratorTagDemo extends ActionSupport implements Validateable private Integer count; private Integer start; - + @Override public void validate() { if (iteratorValue == null || iteratorValue.trim().length() <= 0) { addFieldError("iteratorValue1", "iterator value 1 cannot be empty"); @@ -43,34 +44,34 @@ public void validate() { } } - public String getIteratorValue() { return this.iteratorValue; } + @StrutsParameter public void setIteratorValue(String iteratorValue) { this.iteratorValue = iteratorValue; } - public Integer getCount() { return this.count; } + @StrutsParameter public void setCount(Integer count) { this.count = count; } - public Integer getStart() { return this.start; } + @StrutsParameter public void setStart(Integer start) { this.start = start; } - + @Override public String input() throws Exception { return SUCCESS; } @@ -78,6 +79,4 @@ public String input() throws Exception { public String submit() throws Exception { return SUCCESS; } - - } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/tiles/TilesAnnotationsAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/tiles/TilesAnnotationsAction.java index 2b789c2d8c..f60a673e51 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/tiles/TilesAnnotationsAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/tiles/TilesAnnotationsAction.java @@ -24,7 +24,7 @@ import org.apache.struts2.tiles.annotation.TilesDefinition; import org.apache.struts2.tiles.annotation.TilesPutAttribute; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; @Namespace("/tiles") @ParentPackage("tiles") diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java index 680fde6492..0b731e325c 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/token/TokenAction.java @@ -20,8 +20,9 @@ */ package org.apache.struts2.showcase.token; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionContext; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import java.util.Date; @@ -76,6 +77,7 @@ public int getAmount() { return amount; } + @StrutsParameter public void setAmount(int amount) { this.amount = amount; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java index 9e04cd0947..775de00442 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AbstractValidationActionSupport.java @@ -20,7 +20,7 @@ */ package org.apache.struts2.showcase.validation; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; /** */ @@ -30,6 +30,7 @@ public String submit() throws Exception { return "success"; } + @Override public String input() throws Exception { return "input"; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AjaxFormSubmitAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AjaxFormSubmitAction.java index 50ff53f988..6fdafed611 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AjaxFormSubmitAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AjaxFormSubmitAction.java @@ -1,21 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ package org.apache.struts2.showcase.validation; -import java.sql.Date; +import org.apache.struts2.validator.annotations.DateRangeFieldValidator; +import org.apache.struts2.validator.annotations.EmailValidator; +import org.apache.struts2.validator.annotations.FieldExpressionValidator; +import org.apache.struts2.validator.annotations.IntRangeFieldValidator; +import org.apache.struts2.validator.annotations.RegexFieldValidator; +import org.apache.struts2.validator.annotations.RequiredFieldValidator; +import org.apache.struts2.validator.annotations.RequiredStringValidator; +import org.apache.struts2.validator.annotations.StringLengthFieldValidator; +import org.apache.struts2.validator.annotations.UrlValidator; +import org.apache.struts2.interceptor.parameter.StrutsParameter; -import com.opensymphony.xwork2.validator.annotations.DateRangeFieldValidator; -import com.opensymphony.xwork2.validator.annotations.EmailValidator; -import com.opensymphony.xwork2.validator.annotations.FieldExpressionValidator; -import com.opensymphony.xwork2.validator.annotations.IntRangeFieldValidator; -import com.opensymphony.xwork2.validator.annotations.RegexFieldValidator; -import com.opensymphony.xwork2.validator.annotations.RequiredFieldValidator; -import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator; -import com.opensymphony.xwork2.validator.annotations.StringLengthFieldValidator; -import com.opensymphony.xwork2.validator.annotations.UrlValidator; +import java.sql.Date; /** * - */ -/** * Example Action that shows how forms can be validated and submitted via AJAX * only. Form-submit-and-page-reload functionality of browsers is not used for * this action. @@ -56,9 +73,10 @@ public Date getDateValidatorField() { } @DateRangeFieldValidator( - min="01/01/1990", - max="01/01/2000", + min="01/01/1990", + max="01/01/2000", message="must be a min 01-01-1990 max 01-01-2000 if supplied") + @StrutsParameter public void setDateValidatorField(Date dateValidatorField) { this.dateValidatorField = dateValidatorField; } @@ -68,6 +86,7 @@ public String getEmailValidatorField() { } @EmailValidator(message="must be a valid email if supplied") + @StrutsParameter public void setEmailValidatorField(String emailValidatorField) { this.emailValidatorField = emailValidatorField; } @@ -77,6 +96,7 @@ public Integer getIntegerValidatorField() { } @IntRangeFieldValidator(min="1", max="10", message="must be integer min 1 max 10 if supplied") + @StrutsParameter public void setIntegerValidatorField(Integer integerValidatorField) { this.integerValidatorField = integerValidatorField; } @@ -86,8 +106,9 @@ public String getRegexValidatorField() { } @RegexFieldValidator( - regex="[^<>]+", + regex="[^<>]+", message="regexValidatorField must match a regexp (.*\\.txt) if specified") + @StrutsParameter public void setRegexValidatorField(String regexValidatorField) { this.regexValidatorField = regexValidatorField; } @@ -97,6 +118,7 @@ public String getRequiredStringValidatorField() { } @RequiredStringValidator(trim=true, message="required and must be string") + @StrutsParameter public void setRequiredStringValidatorField(String requiredStringValidatorField) { this.requiredStringValidatorField = requiredStringValidatorField; } @@ -106,6 +128,7 @@ public String getRequiredValidatorField() { } @RequiredFieldValidator(message="required") + @StrutsParameter public void setRequiredValidatorField(String requiredValidatorField) { this.requiredValidatorField = requiredValidatorField; } @@ -115,10 +138,11 @@ public String getStringLengthValidatorField() { } @StringLengthFieldValidator( - minLength="2", - maxLength="4", - trim=true, + minLength="2", + maxLength="4", + trim=true, message="must be a String of a specific greater than 1 less than 5 if specified") + @StrutsParameter public void setStringLengthValidatorField(String stringLengthValidatorField) { this.stringLengthValidatorField = stringLengthValidatorField; } @@ -128,10 +152,10 @@ public String getFieldExpressionValidatorField() { } @FieldExpressionValidator( - expression = "(fieldExpressionValidatorField == requiredValidatorField)", + expression = "(fieldExpressionValidatorField == requiredValidatorField)", message = "must be the same as the Required Validator Field if specified") - public void setFieldExpressionValidatorField( - String fieldExpressionValidatorField) { + @StrutsParameter + public void setFieldExpressionValidatorField(String fieldExpressionValidatorField) { this.fieldExpressionValidatorField = fieldExpressionValidatorField; } @@ -140,6 +164,7 @@ public String getUrlValidatorField() { } @UrlValidator(message="must be a valid url if supplied") + @StrutsParameter public void setUrlValidatorField(String urlValidatorField) { this.urlValidatorField = urlValidatorField; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AjaxFormSubmitSuccessAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AjaxFormSubmitSuccessAction.java index 6eca3fc68d..76866adc9f 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AjaxFormSubmitSuccessAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/AjaxFormSubmitSuccessAction.java @@ -1,3 +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. + */ package org.apache.struts2.showcase.validation; public class AjaxFormSubmitSuccessAction { diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/BeanValidationExampleAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/BeanValidationExampleAction.java index 67190e0358..96a53942ea 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/BeanValidationExampleAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/BeanValidationExampleAction.java @@ -20,29 +20,32 @@ */ package org.apache.struts2.showcase.validation; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; import org.apache.struts.beanvalidation.constraints.FieldMatch; import org.apache.struts2.convention.annotation.Action; import org.apache.struts2.convention.annotation.Namespace; import org.apache.struts2.convention.annotation.ParentPackage; import org.apache.struts2.convention.annotation.Result; +import org.apache.struts2.interceptor.parameter.StrutsParameter; import org.apache.struts2.interceptor.validation.SkipValidation; -import org.hibernate.validator.constraints.Email; -import org.hibernate.validator.constraints.NotBlank; import org.hibernate.validator.constraints.ScriptAssert; import org.hibernate.validator.constraints.URL; -import javax.validation.constraints.*; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.Max; +import jakarta.validation.constraints.Min; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Pattern; +import jakarta.validation.constraints.Size; import java.util.Date; -/** - * - */ +// @Namespace("/bean-validation") @ParentPackage("bean-validation") @Action(results = { - @Result(name = "input", location = "bean-validation.jsp"), - @Result(name = "success", location = "/WEB-INF/validation/successFieldValidatorsExample.jsp") + @Result(name = "input", location = "bean-validation.jsp"), + @Result(name = "success", location = "/WEB-INF/validation/successFieldValidatorsExample.jsp") }) @FieldMatch(first = "fieldExpressionValidatorField", second = "requiredValidatorField", message = "requiredValidatorField and fieldExpressionValidatorField are not matching") @ScriptAssert(lang = "javascript", script = "_this.dateValidatorField != null && _this.dateValidatorField.before(new java.util.Date())", message = "Date need to before now") @@ -82,10 +85,10 @@ public class BeanValidationExampleAction extends ActionSupport { private String fieldExpressionValidatorField = null; @Action(value = "bean-validation", results = { - @Result(name = "success", location = "bean-validation.jsp") + @Result(name = "success", location = "bean-validation.jsp") }) @SkipValidation - public String beanValidation(){ + public String beanValidation() { return SUCCESS; } @@ -93,6 +96,7 @@ public Date getDateValidatorField() { return dateValidatorField; } + @StrutsParameter public void setDateValidatorField(Date dateValidatorField) { this.dateValidatorField = dateValidatorField; } @@ -101,6 +105,7 @@ public String getEmailValidatorField() { return emailValidatorField; } + @StrutsParameter public void setEmailValidatorField(String emailValidatorField) { this.emailValidatorField = emailValidatorField; } @@ -109,6 +114,7 @@ public Integer getIntegerValidatorField() { return integerValidatorField; } + @StrutsParameter public void setIntegerValidatorField(Integer integerValidatorField) { this.integerValidatorField = integerValidatorField; } @@ -117,6 +123,7 @@ public String getRegexValidatorField() { return regexValidatorField; } + @StrutsParameter public void setRegexValidatorField(String regexValidatorField) { this.regexValidatorField = regexValidatorField; } @@ -125,6 +132,7 @@ public String getRequiredStringValidatorField() { return requiredStringValidatorField; } + @StrutsParameter public void setRequiredStringValidatorField(String requiredStringValidatorField) { this.requiredStringValidatorField = requiredStringValidatorField; } @@ -133,6 +141,7 @@ public String getRequiredValidatorField() { return requiredValidatorField; } + @StrutsParameter public void setRequiredValidatorField(String requiredValidatorField) { this.requiredValidatorField = requiredValidatorField; } @@ -141,6 +150,7 @@ public String getStringLengthValidatorField() { return stringLengthValidatorField; } + @StrutsParameter public void setStringLengthValidatorField(String stringLengthValidatorField) { this.stringLengthValidatorField = stringLengthValidatorField; } @@ -149,8 +159,8 @@ public String getFieldExpressionValidatorField() { return fieldExpressionValidatorField; } - public void setFieldExpressionValidatorField( - String fieldExpressionValidatorField) { + @StrutsParameter + public void setFieldExpressionValidatorField(String fieldExpressionValidatorField) { this.fieldExpressionValidatorField = fieldExpressionValidatorField; } @@ -158,13 +168,10 @@ public String getUrlValidatorField() { return urlValidatorField; } + @StrutsParameter public void setUrlValidatorField(String urlValidatorField) { this.urlValidatorField = urlValidatorField; } } -/** - * - */ - - +// diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java index a9e02deabf..9639bacd17 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.java @@ -20,6 +20,8 @@ */ package org.apache.struts2.showcase.validation; +import org.apache.struts2.interceptor.parameter.StrutsParameter; + import java.sql.Date; /** @@ -44,6 +46,7 @@ public Date getDateValidatorField() { return dateValidatorField; } + @StrutsParameter public void setDateValidatorField(Date dateValidatorField) { this.dateValidatorField = dateValidatorField; } @@ -52,6 +55,7 @@ public String getEmailValidatorField() { return emailValidatorField; } + @StrutsParameter public void setEmailValidatorField(String emailValidatorField) { this.emailValidatorField = emailValidatorField; } @@ -60,6 +64,7 @@ public Integer getIntegerValidatorField() { return integerValidatorField; } + @StrutsParameter public void setIntegerValidatorField(Integer integerValidatorField) { this.integerValidatorField = integerValidatorField; } @@ -68,6 +73,7 @@ public String getRegexValidatorField() { return regexValidatorField; } + @StrutsParameter public void setRegexValidatorField(String regexValidatorField) { this.regexValidatorField = regexValidatorField; } @@ -76,6 +82,7 @@ public String getRequiredStringValidatorField() { return requiredStringValidatorField; } + @StrutsParameter public void setRequiredStringValidatorField(String requiredStringValidatorField) { this.requiredStringValidatorField = requiredStringValidatorField; } @@ -84,6 +91,7 @@ public String getRequiredValidatorField() { return requiredValidatorField; } + @StrutsParameter public void setRequiredValidatorField(String requiredValidatorField) { this.requiredValidatorField = requiredValidatorField; } @@ -92,6 +100,7 @@ public String getStringLengthValidatorField() { return stringLengthValidatorField; } + @StrutsParameter public void setStringLengthValidatorField(String stringLengthValidatorField) { this.stringLengthValidatorField = stringLengthValidatorField; } @@ -100,6 +109,7 @@ public String getFieldExpressionValidatorField() { return fieldExpressionValidatorField; } + @StrutsParameter public void setFieldExpressionValidatorField( String fieldExpressionValidatorField) { this.fieldExpressionValidatorField = fieldExpressionValidatorField; @@ -109,6 +119,7 @@ public String getUrlValidatorField() { return urlValidatorField; } + @StrutsParameter public void setUrlValidatorField(String urlValidatorField) { this.urlValidatorField = urlValidatorField; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java index 2b16d9b769..d263e5db74 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction.java @@ -20,6 +20,8 @@ */ package org.apache.struts2.showcase.validation; +import org.apache.struts2.interceptor.parameter.StrutsParameter; + /** */ @@ -37,6 +39,7 @@ public String getSomeText() { return someText; } + @StrutsParameter public void setSomeText(String someText) { this.someText = someText; } @@ -45,6 +48,7 @@ public String getSomeTextRetype() { return someTextRetype; } + @StrutsParameter public void setSomeTextRetype(String someTextRetype) { this.someTextRetype = someTextRetype; } @@ -53,6 +57,7 @@ public String getSomeTextRetypeAgain() { return someTextRetypeAgain; } + @StrutsParameter public void setSomeTextRetypeAgain(String someTextRetypeAgain) { this.someTextRetypeAgain = someTextRetypeAgain; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java index 57a583193f..7ac1f15f74 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/QuizAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.validation; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; /** */ @@ -39,6 +40,7 @@ public String getName() { return name; } + @StrutsParameter public void setName(String name) { this.name = name; } @@ -47,6 +49,7 @@ public int getAge() { return age; } + @StrutsParameter public void setAge(int age) { this.age = age; } @@ -55,6 +58,7 @@ public String getAnswer() { return answer; } + @StrutsParameter public void setAnswer(String answer) { this.answer = answer; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java index 5a990d01aa..bdaa8aa2c6 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/SubmitApplication.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.validation; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; /** * @version $Date$ $Id$ @@ -30,6 +31,7 @@ public class SubmitApplication extends ActionSupport { private String name; private Integer age; + @StrutsParameter public void setName(String name) { this.name = name; } @@ -38,6 +40,7 @@ public String getName() { return this.name; } + @StrutsParameter public void setAge(Integer age) { this.age = age; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java index 7c13f35b69..6cba476128 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction.java @@ -23,12 +23,15 @@ // START SNIPPET: visitorValidatorsExample +import org.apache.struts2.interceptor.parameter.StrutsParameter; + public class VisitorValidatorsExampleAction extends AbstractValidationActionSupport { private static final long serialVersionUID = 4375454086939598216L; private User user; + @StrutsParameter(depth = 1) public User getUser() { return user; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java index 8ff6859bb0..1814c0fa5d 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/LongProcessAction.java @@ -20,7 +20,8 @@ */ package org.apache.struts2.showcase.wait; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; +import org.apache.struts2.interceptor.parameter.StrutsParameter; /** * Example to illustrate the execAndWait interceptor. @@ -41,6 +42,7 @@ public int getTime() { return time; } + @StrutsParameter public void setTime(int time) { this.time = time; } diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/ThreadPoolExecutorProvider.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/ThreadPoolExecutorProvider.java new file mode 100644 index 0000000000..ffffc7a1d0 --- /dev/null +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/wait/ThreadPoolExecutorProvider.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.struts2.showcase.wait; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.struts2.interceptor.exec.ExecutorProvider; + +import java.util.concurrent.ExecutorService; +import java.util.concurrent.LinkedBlockingDeque; +import java.util.concurrent.ThreadPoolExecutor; +import java.util.concurrent.TimeUnit; + +public class ThreadPoolExecutorProvider implements ExecutorProvider { + + private static final Logger LOG = LogManager.getLogger(ThreadPoolExecutorProvider.class); + + private final ExecutorService executor; + + public ThreadPoolExecutorProvider() { + this.executor = new ThreadPoolExecutor(1, 2, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingDeque<>()); + } + + @Override + public void execute(Runnable task) { + LOG.info("Executing task: {}", task); + executor.execute(task); + } + + @Override + public boolean isShutdown() { + return executor.isShutdown(); + } + + @Override + public void shutdown() { + LOG.info("Shutting down executor"); + executor.shutdown(); + } +} diff --git a/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java b/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java index 059b300afb..0075e451e1 100644 --- a/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java +++ b/apps/showcase/src/main/java/org/apache/struts2/showcase/xslt/JVMAction.java @@ -20,10 +20,12 @@ */ package org.apache.struts2.showcase.xslt; -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.interceptor.ServletRequestAware; +import org.apache.struts2.ActionSupport; + +import jakarta.servlet.http.HttpServletRequest; + +import org.apache.struts2.action.ServletRequestAware; -import javax.servlet.http.HttpServletRequest; import java.util.Map; import java.util.Properties; @@ -53,10 +55,6 @@ public HttpServletRequest getServletRequest() { return servletRequest; } - public void setServletRequest(HttpServletRequest servletRequest) { - this.servletRequest = servletRequest; - } - public Map getEnvironment() { return environment; } @@ -74,7 +72,7 @@ public void setInfo(ImportantInfo info) { this.info = info; } - public class ImportantInfo { + public static class ImportantInfo { private String classpath; private Properties systemProperties; @@ -100,4 +98,9 @@ public void setSystemProperties(Properties systemProperties) { this.systemProperties = systemProperties; } } + + @Override + public void withServletRequest(HttpServletRequest request) { + this.servletRequest = request; + } } diff --git a/apps/showcase/src/main/resources/globalMessages.properties b/apps/showcase/src/main/resources/globalMessages.properties index d3417f7885..51f6e6a23f 100644 --- a/apps/showcase/src/main/resources/globalMessages.properties +++ b/apps/showcase/src/main/resources/globalMessages.properties @@ -1,3 +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. +# format.number = {0,number,#0.0##} save=Save diff --git a/apps/showcase/src/main/resources/globalMessages_de.properties b/apps/showcase/src/main/resources/globalMessages_de.properties index 0dc66efa83..1d20fba35f 100644 --- a/apps/showcase/src/main/resources/globalMessages_de.properties +++ b/apps/showcase/src/main/resources/globalMessages_de.properties @@ -1,3 +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. +# save=Speichern item.edit={0} bearbeiten diff --git a/apps/showcase/src/main/resources/globalMessages_en.properties b/apps/showcase/src/main/resources/globalMessages_en.properties index e69de29bb2..f05fa49110 100644 --- a/apps/showcase/src/main/resources/globalMessages_en.properties +++ b/apps/showcase/src/main/resources/globalMessages_en.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/apps/showcase/src/main/resources/log4j2.xml b/apps/showcase/src/main/resources/log4j2.xml index 913b299306..d7836c7179 100644 --- a/apps/showcase/src/main/resources/log4j2.xml +++ b/apps/showcase/src/main/resources/log4j2.xml @@ -1,16 +1,34 @@ + - + - - - + - \ No newline at end of file + diff --git a/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl b/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl index 544f44e60f..50506fca6c 100644 --- a/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl +++ b/apps/showcase/src/main/resources/myTemplateDir/myTheme/myAnotherTemplate.ftl @@ -1,6 +1,26 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +-->

Freemarker Custom Template - -parameter 'paramName' - ${parameters.paramName} +parameter 'paramName' - ${attributes.paramName}

diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/DateAction.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/DateAction.properties index d49c743a5e..256d9bd6f9 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/DateAction.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/DateAction.properties @@ -1 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# struts.date.format=yyyy/MM/dd hh:mm:ss \ No newline at end of file diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml index 383eeb86f0..1c63b912fa 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/LotsOfRichtexteditorAction-lotsOfRichtexteditorSubmit-validation.xml @@ -1,30 +1,51 @@ - + + - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + Description1 Is Required !!! - + Description2 Is Required !!! - + Description3 Is Required !!! - + Description4 Is Required !!! - - + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/UITagExample-conversion.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/UITagExample-conversion.properties index 2415dcf3c5..fc304f7b0d 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/UITagExample-conversion.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/UITagExample-conversion.properties @@ -1 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# Element_friends = java.lang.String diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-conversion.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-conversion.properties index 21d3eda97d..a67827d434 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-conversion.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-conversion.properties @@ -1 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# Element_selectedSkills=java.lang.String diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml index a82f7654b1..a19d0449d2 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction-validation.xml @@ -1,5 +1,25 @@ - + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction.properties index e2e548b3ce..836c376865 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction.properties @@ -1,3 +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. +# employee=Employee employee.firstName=First Name employee.lastName=Last Name diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_de.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_de.properties index ca594de4d9..2be81dee85 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_de.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_de.properties @@ -1,9 +1,27 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# employee=Mitarbeiter employee.firstName=Vorname employee.lastName=Nachname employee.description=Beschreibung -employee.id.required=ID mu angegeben werden -employee.lastName.required=Nachname wird bentigt -employee.birthDate.required=Geburtsdatum wird bentigt -employee.backtolist=Zurck zur Mitarbeiterliste +employee.id.required=ID muß angegeben werden +employee.lastName.required=Nachname wird benötigt +employee.birthDate.required=Geburtsdatum wird benötigt +employee.backtolist=Zurück zur Mitarbeiterliste diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_en.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_en.properties index e69de29bb2..f05fa49110 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_en.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/EmployeeAction_en.properties @@ -0,0 +1,18 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT 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/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml index 911e1fad31..5c2574a4da 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction-validation.xml @@ -1,5 +1,25 @@ - + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction.properties index 27b7c81df7..b533fa6101 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction.properties @@ -1,3 +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. +# skill=Skill skill.name=Name skill.description=Description diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction_de.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction_de.properties index 7c7156f71b..ba6896b4fe 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction_de.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/action/SkillAction_de.properties @@ -1,6 +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. +# skill=Kenntnis skill.name=Name skill.description=Beschreibung skill.name.required=Name muss angegeben werden -skill.backtolist=Zurck zur Kenntnis Liste +skill.backtolist=Zurück zur Kenntnis Liste diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/AddressAction-conversion.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/AddressAction-conversion.properties index 1a6d70055b..d836489352 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/AddressAction-conversion.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/AddressAction-conversion.properties @@ -1,4 +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. +# KeyProperty_addresses=id Element_addresses=org.apache.struts2.showcase.conversion.Address CreateIfNull_addresses=true diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/OperationsEnumAction-conversion.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/OperationsEnumAction-conversion.properties index 621beafba0..7b09406179 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/OperationsEnumAction-conversion.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/OperationsEnumAction-conversion.properties @@ -1,4 +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. +# selectedOperations=org.apache.struts2.showcase.conversion.EnumTypeConverter Element_selectedOperations=org.apache.struts2.showcase.conversion.OperationsEnum diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/PersonAction-conversion.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/PersonAction-conversion.properties index 12f602f168..335a74f87f 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/PersonAction-conversion.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/conversion/PersonAction-conversion.properties @@ -1 +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. +# Element_persons=org.apache.struts2.showcase.conversion.Person diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml index 989656e426..e15b2506f9 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/FileUploadAction-validation.xml @@ -1,12 +1,32 @@ - + + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> - 0]]> + 0]]> File cannot be empty @@ -15,5 +35,4 @@ Caption cannot be empty - - \ No newline at end of file + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction-conversion.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction-conversion.properties index fbf3d7730d..f37c8e7f62 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction-conversion.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/fileupload/MultipleFileUploadUsingListAction-conversion.properties @@ -1 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# Element_upload=java.io.File diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPersonAction-conversion.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPersonAction-conversion.properties index 00b2a03654..2fc9ae189b 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPersonAction-conversion.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPersonAction-conversion.properties @@ -1,3 +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. +# KeyProperty_persons=id Element_persons=org.apache.struts2.showcase.person.Person CreateIfNull_persons=true diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml index 6d7f85fe17..0bd8abe33a 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml @@ -1,4 +1,25 @@ - + + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml index 4d8a374b25..425d4154f3 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/Person-validation.xml @@ -1,4 +1,25 @@ - + + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml index 981cf73e32..07f1ea9ad9 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/tag/nonui/iteratortag/IteratorGeneratorTagDemo-validation.xml @@ -1,8 +1,28 @@ - + - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + @@ -10,13 +30,13 @@ Value must not be empty - - + + Count must be an integer - + - + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-conversion.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-conversion.properties index 2f970dc18b..dca0321ecc 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-conversion.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-conversion.properties @@ -1 +1,19 @@ -dateValidatorField=java.util.Date \ No newline at end of file +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# +dateValidatorField=org.apache.struts2.showcase.chat.DateConverter diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml index 2f5bad26be..2d732c0ab4 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitClientSideValidationExample-validation.xml @@ -1,11 +1,30 @@ - - + + - - - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml index 26a87f3be8..4def409bb2 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction-submitFieldValidatorsExamples-validation.xml @@ -1,11 +1,30 @@ - - - + + - - - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + + + @@ -52,7 +71,7 @@ - ]+ ]]> + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.properties b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.properties index 14f04121a3..2446796745 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.properties +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/FieldValidatorsExampleAction.properties @@ -1 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# i18n.requiredstring=Test String for required Strings... diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml index 71673c1f12..a94a9e2ffd 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/NonFieldValidatorsExampleAction-submitNonFieldValidatorsExamples-validation.xml @@ -1,12 +1,31 @@ - - + - - - - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + + + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml index 4da868ac40..8f7a486045 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/QuizAction-validation.xml @@ -1,9 +1,29 @@ - - + + + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml index ad36c531f8..492475df6d 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/SubmitApplication-submitApplication-validation.xml @@ -1,7 +1,27 @@ + + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml index 7984609c0d..1e3dd4c6ce 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/User-userContext-validation.xml @@ -1,16 +1,35 @@ - - + - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + Name Required - + 1 100 @@ -22,6 +41,6 @@ Birthday Required - + diff --git a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml index 91ddeb6e8d..cb4a8138f0 100644 --- a/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml +++ b/apps/showcase/src/main/resources/org/apache/struts2/showcase/validation/VisitorValidatorsExampleAction-submitVisitorValidatorsExamples-validation.xml @@ -1,9 +1,28 @@ - - + - + "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd"> + @@ -16,5 +35,5 @@ - + diff --git a/apps/showcase/src/main/resources/struts-actionchaining.xml b/apps/showcase/src/main/resources/struts-actionchaining.xml index ab0f2ea5b7..4f39940f06 100644 --- a/apps/showcase/src/main/resources/struts-actionchaining.xml +++ b/apps/showcase/src/main/resources/struts-actionchaining.xml @@ -1,12 +1,32 @@ + - + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> + - actionChain2 + actionChain2 actionChain3 diff --git a/apps/showcase/src/main/resources/struts-async.xml b/apps/showcase/src/main/resources/struts-async.xml new file mode 100644 index 0000000000..178a14dc86 --- /dev/null +++ b/apps/showcase/src/main/resources/struts-async.xml @@ -0,0 +1,49 @@ + + + + + + + + + + newMessages + + + newMessages + + + + + + newMessages + + + newMessages + + + + + + diff --git a/apps/showcase/src/main/resources/struts-conversion.xml b/apps/showcase/src/main/resources/struts-conversion.xml index e597b25c0f..873c0703c0 100644 --- a/apps/showcase/src/main/resources/struts-conversion.xml +++ b/apps/showcase/src/main/resources/struts-conversion.xml @@ -1,15 +1,35 @@ + - + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> + - + /WEB-INF/conversion/index.jsp - + @@ -29,8 +49,8 @@ /WEB-INF/conversion/Person.java.txt - - + + /WEB-INF/conversion/enterAddressInfo.jsp @@ -48,9 +68,9 @@ /WEB-INF/conversion/Address.java.txt - - - + + + /WEB-INF/conversion/enterOperations.jsp @@ -73,6 +93,6 @@ /WEB-INF/conversion/OperationsEnumActionConversion.txt - + - + diff --git a/apps/showcase/src/main/resources/struts-dispatcher.xml b/apps/showcase/src/main/resources/struts-dispatcher.xml new file mode 100644 index 0000000000..9d9ea24e32 --- /dev/null +++ b/apps/showcase/src/main/resources/struts-dispatcher.xml @@ -0,0 +1,40 @@ + + + + + + + + + + /WEB-INF/dispatcher/dispatch-result.jsp + + + + + /dispatcher/dispatch.action + + + + diff --git a/apps/showcase/src/main/resources/struts-filedownload.xml b/apps/showcase/src/main/resources/struts-filedownload.xml index de50f5abd3..5a8b5ae224 100644 --- a/apps/showcase/src/main/resources/struts-filedownload.xml +++ b/apps/showcase/src/main/resources/struts-filedownload.xml @@ -1,7 +1,27 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> diff --git a/apps/showcase/src/main/resources/struts-fileupload.xml b/apps/showcase/src/main/resources/struts-fileupload.xml index d9d0cfcacb..21ce3fb034 100644 --- a/apps/showcase/src/main/resources/struts-fileupload.xml +++ b/apps/showcase/src/main/resources/struts-fileupload.xml @@ -1,11 +1,34 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> + + + - + /WEB-INF/fileupload/upload.jsp @@ -14,12 +37,13 @@ /WEB-INF/fileupload/upload.jsp /WEB-INF/fileupload/upload-success.jsp - + /WEB-INF/fileupload/multipleUploadUsingList.jsp - + + /WEB-INF/fileupload/multipleUploadUsingList.jsp /WEB-INF/fileupload/multiple-success.jsp @@ -29,6 +53,7 @@ + /WEB-INF/fileupload/multipleUploadUsingArray.jsp /WEB-INF/fileupload/multiple-success.jsp diff --git a/apps/showcase/src/main/resources/struts-freemarker.xml b/apps/showcase/src/main/resources/struts-freemarker.xml index 9a6c9017f1..e4dd3f1a79 100644 --- a/apps/showcase/src/main/resources/struts-freemarker.xml +++ b/apps/showcase/src/main/resources/struts-freemarker.xml @@ -1,16 +1,36 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> /WEB-INF/freemarker/customFreemarkerManagerUsage.ftl - + /WEB-INF/freemarker/standardTags.ftl - + diff --git a/apps/showcase/src/main/resources/struts-hangman.xml b/apps/showcase/src/main/resources/struts-hangman.xml index b8540630a7..510b4e7f6d 100644 --- a/apps/showcase/src/main/resources/struts-hangman.xml +++ b/apps/showcase/src/main/resources/struts-hangman.xml @@ -1,7 +1,27 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> @@ -21,9 +41,9 @@ /WEB-INF/hangman/hangmanNonAjax.ftl - - - + + + /WEB-INF/hangman/blank.ftl @@ -41,4 +61,4 @@ /WEB-INF/hangman/updateGuessLeft.ftl - + diff --git a/apps/showcase/src/main/resources/struts-interactive.xml b/apps/showcase/src/main/resources/struts-interactive.xml index 7c50d37538..c057a39079 100644 --- a/apps/showcase/src/main/resources/struts-interactive.xml +++ b/apps/showcase/src/main/resources/struts-interactive.xml @@ -1,7 +1,27 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> @@ -18,4 +38,4 @@ - \ No newline at end of file + diff --git a/apps/showcase/src/main/resources/struts-model-driven.xml b/apps/showcase/src/main/resources/struts-model-driven.xml index 56e4bdfbe7..2183c203a4 100644 --- a/apps/showcase/src/main/resources/struts-model-driven.xml +++ b/apps/showcase/src/main/resources/struts-model-driven.xml @@ -1,7 +1,27 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> @@ -9,11 +29,10 @@ /WEB-INF/modelDriven/modelDriven.jsp - + /WEB-INF/modelDriven/modelDrivenResult.jsp - - \ No newline at end of file + diff --git a/apps/showcase/src/main/resources/struts-params-annotation.xml b/apps/showcase/src/main/resources/struts-params-annotation.xml new file mode 100644 index 0000000000..db39928844 --- /dev/null +++ b/apps/showcase/src/main/resources/struts-params-annotation.xml @@ -0,0 +1,32 @@ + + + + + + + + /WEB-INF/paramsannotation.vm + + + diff --git a/apps/showcase/src/main/resources/struts-person.xml b/apps/showcase/src/main/resources/struts-person.xml index e880e5b27a..0a97104e5e 100644 --- a/apps/showcase/src/main/resources/struts-person.xml +++ b/apps/showcase/src/main/resources/struts-person.xml @@ -1,7 +1,27 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> diff --git a/apps/showcase/src/main/resources/struts-tags-non-ui.xml b/apps/showcase/src/main/resources/struts-tags-non-ui.xml index 9ecf1528be..c6a2ee3861 100644 --- a/apps/showcase/src/main/resources/struts-tags-non-ui.xml +++ b/apps/showcase/src/main/resources/struts-tags-non-ui.xml @@ -1,14 +1,34 @@ + - + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> + - + - + /WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp @@ -26,11 +46,11 @@ /WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp - + - + /WEB-INF/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp @@ -40,8 +60,8 @@ /WEB-INF/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp - - + + @@ -54,8 +74,8 @@ /WEB-INF/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp - - + + @@ -68,7 +88,7 @@ /WEB-INF/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp - + @@ -81,14 +101,14 @@ /WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp - + /WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl - + /WEB-INF/tags/non-ui/actionPrefix/normalSubmit.ftl @@ -111,7 +131,7 @@ /WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl - + @@ -131,7 +151,7 @@ /WEB-INF/tags/non-ui/date.jsp - + /WEB-INF/tags/non-ui/debug.jsp diff --git a/apps/showcase/src/main/resources/struts-tags-ui.xml b/apps/showcase/src/main/resources/struts-tags-ui.xml index 659e97934c..0580d5b94c 100644 --- a/apps/showcase/src/main/resources/struts-tags-ui.xml +++ b/apps/showcase/src/main/resources/struts-tags-ui.xml @@ -1,10 +1,30 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> - + /WEB-INF/tags/ui/example.jsp /WEB-INF/tags/ui/example.jsp diff --git a/apps/showcase/src/main/resources/struts-tags.xml b/apps/showcase/src/main/resources/struts-tags.xml index 8485a64f0d..eb7ee23efe 100644 --- a/apps/showcase/src/main/resources/struts-tags.xml +++ b/apps/showcase/src/main/resources/struts-tags.xml @@ -1,7 +1,27 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> diff --git a/apps/showcase/src/main/resources/struts-tiles.xml b/apps/showcase/src/main/resources/struts-tiles.xml index caa0727f03..7175d71444 100644 --- a/apps/showcase/src/main/resources/struts-tiles.xml +++ b/apps/showcase/src/main/resources/struts-tiles.xml @@ -1,7 +1,27 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> diff --git a/apps/showcase/src/main/resources/struts-token.xml b/apps/showcase/src/main/resources/struts-token.xml index 8b545df041..2b4a18d0e5 100644 --- a/apps/showcase/src/main/resources/struts-token.xml +++ b/apps/showcase/src/main/resources/struts-token.xml @@ -1,7 +1,27 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> @@ -28,7 +48,7 @@ /WEB-INF/token/doublePost.jsp - /WEB-INF/token/transferDone.jsp + /WEB-INF/token/transferDone.jsp @@ -42,7 +62,7 @@ /WEB-INF/token/doublePost.jsp - /WEB-INF/token/transferDone.jsp + /WEB-INF/token/transferDone.jsp diff --git a/apps/showcase/src/main/resources/struts-validation.xml b/apps/showcase/src/main/resources/struts-validation.xml index 63fcd79709..38e2adf83f 100755 --- a/apps/showcase/src/main/resources/struts-validation.xml +++ b/apps/showcase/src/main/resources/struts-validation.xml @@ -1,8 +1,28 @@ + - + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> + @@ -14,28 +34,28 @@ - /WEB-INF/validation/index.jsp + index.jsp - quiz-basic.jsp - quiz-success.jsp + /WEB-INF/validation/quiz-basic.jsp + /WEB-INF/validation/quiz-success.jsp - quiz-client.jsp - quiz-success.jsp + /WEB-INF/validation/quiz-client.jsp + /WEB-INF/validation/quiz-success.jsp - - quiz-client-css.jsp - quiz-success.jsp + + /WEB-INF/validation/quiz-client-css.jsp + /WEB-INF/validation/quiz-success.jsp - quiz-ajax.jsp - quiz-success.jsp + /WEB-INF/validation/quiz-ajax.jsp + /WEB-INF/validation/quiz-success.jsp @@ -49,7 +69,7 @@ /WEB-INF/validation/ajaxFormSubmitSuccess.jsp - + @@ -58,46 +78,46 @@ index.jsp - - + + - + /WEB-INF/validation/fieldValidatorsExample.jsp - + /WEB-INF/validation/fieldValidatorsExample.jsp /WEB-INF/validation/successFieldValidatorsExample.jsp - - - + + + - + /WEB-INF/validation/nonFieldValidatorsExample.jsp - + /WEB-INF/validation/nonFieldValidatorsExample.jsp /WEB-INF/validation/successNonFieldValidatorsExample.jsp - - - + + + - + /WEB-INF/validation/visitorValidatorsExample.jsp - + /WEB-INF/validation/visitorValidatorsExample.jsp /WEB-INF/validation/successVisitorValidatorsExample.jsp @@ -121,7 +141,7 @@ - + STORE @@ -148,7 +168,7 @@ /WEB-INF/validation/storeErrorsAcrossRequestCancel.jsp - + - + diff --git a/apps/showcase/src/main/resources/struts-wait.xml b/apps/showcase/src/main/resources/struts-wait.xml index 1a5556d733..b68431c8af 100644 --- a/apps/showcase/src/main/resources/struts-wait.xml +++ b/apps/showcase/src/main/resources/struts-wait.xml @@ -1,10 +1,40 @@ + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> + + + + + + + + /WEB-INF/wait/index.jsp + /WEB-INF/wait/example1.jsp diff --git a/apps/showcase/src/main/resources/struts-xslt.xml b/apps/showcase/src/main/resources/struts-xslt.xml index d3a040bb74..663e84e93e 100644 --- a/apps/showcase/src/main/resources/struts-xslt.xml +++ b/apps/showcase/src/main/resources/struts-xslt.xml @@ -1,11 +1,30 @@ - + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> - + @@ -17,7 +36,7 @@ info.classpath - + info diff --git a/apps/showcase/src/main/resources/struts.xml b/apps/showcase/src/main/resources/struts.xml index 11ca7246a9..45ab3a5e0d 100644 --- a/apps/showcase/src/main/resources/struts.xml +++ b/apps/showcase/src/main/resources/struts.xml @@ -1,8 +1,27 @@ - + + "-//Apache Software Foundation//DTD Struts Configuration 6.0//EN" + "https://struts.apache.org/dtds/struts-6.0.dtd"> @@ -15,6 +34,17 @@ + + + + + @@ -25,6 +55,8 @@ + + @@ -55,6 +87,12 @@ + + + + + + diff --git a/apps/showcase/src/main/resources/template/ajaxErrorContainers/actionerror.ftl b/apps/showcase/src/main/resources/template/ajaxErrorContainers/actionerror.ftl index 3f7d8ab52c..6f3e881ed7 100644 --- a/apps/showcase/src/main/resources/template/ajaxErrorContainers/actionerror.ftl +++ b/apps/showcase/src/main/resources/template/ajaxErrorContainers/actionerror.ftl @@ -1,7 +1,5 @@ <#-- /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -24,22 +22,22 @@ Make sure element is always present. To be filled later via JS. --> -<#if parameters.id??> - id="${parameters.id?html}"<#rt/> - -<#if parameters.cssClass??> - class="${parameters.cssClass?html}"<#rt/> +<#if attributes.id??> + id="${attributes.id}"<#rt/> + +<#if attributes.cssClass??> + class="${attributes.cssClass}"<#rt/> <#else> class="errorMessage"<#rt/> -<#if parameters.cssStyle??> - style="${parameters.cssStyle?html}"<#rt/> +<#if attributes.cssStyle??> + style="${attributes.cssStyle}"<#rt/> > <#if (actionErrors?? && actionErrors?size > 0)> <#list actionErrors as error> <#if error??> -
  • <#if parameters.escape>${error!?html}<#else>${error!}<#rt/>
  • <#rt/> +
  • <#if attributes.escape>${error!}<#else>${error!}<#rt/>
  • <#rt/> diff --git a/apps/showcase/src/main/resources/template/ajaxErrorContainers/controlfooter.ftl b/apps/showcase/src/main/resources/template/ajaxErrorContainers/controlfooter.ftl index 7f95111f3d..3b94f28c01 100644 --- a/apps/showcase/src/main/resources/template/ajaxErrorContainers/controlfooter.ftl +++ b/apps/showcase/src/main/resources/template/ajaxErrorContainers/controlfooter.ftl @@ -1,7 +1,5 @@ <#-- /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,17 +18,17 @@ * under the License. */ --> -${parameters.after!}<#t/> +${attributes.after!}<#t/> <#lt/> -<#if (parameters.errorposition!"top") == 'bottom'> -<#assign hasFieldErrors = parameters.name?? && fieldErrors?? && fieldErrors[parameters.name]??/> +<#if (attributes.errorposition!"top") == 'bottom'> +<#assign hasFieldErrors = attributes.name?? && fieldErrors?? && fieldErrors.get(attributes.name)??/> <#if hasFieldErrors> - + <#rt/> <#if hasFieldErrors> - <#list fieldErrors[parameters.name] as error> -
    ${error?html}
    <#t/> + <#list fieldErrors.get(attributes.name) as error> +
    ${error}
    <#t/> <#lt/> diff --git a/apps/showcase/src/main/resources/template/ajaxErrorContainers/controlheader-core.ftl b/apps/showcase/src/main/resources/template/ajaxErrorContainers/controlheader-core.ftl index c07b867b03..c75fbef9fb 100644 --- a/apps/showcase/src/main/resources/template/ajaxErrorContainers/controlheader-core.ftl +++ b/apps/showcase/src/main/resources/template/ajaxErrorContainers/controlheader-core.ftl @@ -1,7 +1,5 @@ <#-- /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -23,37 +21,37 @@ <#-- Always include elements to show errors. They may be filled later via AJAX. --> -<#assign hasFieldErrors = parameters.name?? && fieldErrors?? && fieldErrors[parameters.name]??/> -<#if (parameters.errorposition!"top") == 'top'> - - <#rt/> +<#assign hasFieldErrors = attributes.name?? && fieldErrors?? && fieldErrors.get(attributes.name)??/> +<#if (attributes.errorposition!"top") == 'top'> + + <#rt/> <#if hasFieldErrors> - <#list fieldErrors[parameters.name] as error> -
    ${error?html}
    <#t/> + <#list fieldErrors.get(attributes.name) as error> +
    ${error}
    <#t/> <#lt/> -<#if !parameters.labelposition?? && (parameters.form.labelposition)??> -<#assign labelpos = parameters.form.labelposition/> -<#elseif parameters.labelposition??> -<#assign labelpos = parameters.labelposition/> +<#if !attributes.labelPosition?? && (attributes.form.labelPosition)??> +<#assign labelPos = attributes.form.labelPosition/> +<#elseif attributes.labelPosition??> +<#assign labelpos = attributes.labelPosition/> <#-- if the label position is top, then give the label it's own row in the table --> -<#if (labelpos!"") == 'top'> +<#if (labelPos!"") == 'top'> <#rt/> <#else> <#rt/> -<#if parameters.label??> +<#if attributes.label??> <#t/> <#lt/> <#-- add the extra row --> -<#if (labelpos!"") == 'top'> +<#if (labelPos!"") == 'top'> diff --git a/apps/showcase/src/main/resources/template/ajaxErrorContainers/theme.properties b/apps/showcase/src/main/resources/template/ajaxErrorContainers/theme.properties index 81346c7078..c69b670f1c 100644 --- a/apps/showcase/src/main/resources/template/ajaxErrorContainers/theme.properties +++ b/apps/showcase/src/main/resources/template/ajaxErrorContainers/theme.properties @@ -1,6 +1,4 @@ # -# $Id$ -# # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information diff --git a/apps/showcase/src/main/resources/velocity.properties b/apps/showcase/src/main/resources/velocity.properties index 6299831743..5a0d48b743 100644 --- a/apps/showcase/src/main/resources/velocity.properties +++ b/apps/showcase/src/main/resources/velocity.properties @@ -1 +1,19 @@ +# +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. +# runtime.log.logsystem.class=org.apache.velocity.runtime.log.NullLogChute diff --git a/apps/showcase/src/main/webapp/WEB-INF/actionchaining/actionChainingResult.jsp b/apps/showcase/src/main/webapp/WEB-INF/actionchaining/actionChainingResult.jsp index b5696d6d9c..cf19dc1d87 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/actionchaining/actionChainingResult.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/actionchaining/actionChainingResult.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/applicationContext.xml b/apps/showcase/src/main/webapp/WEB-INF/applicationContext.xml index c4a105954e..ef700ef48f 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/applicationContext.xml +++ b/apps/showcase/src/main/webapp/WEB-INF/applicationContext.xml @@ -1,4 +1,24 @@ + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + - - - + @@ -109,9 +109,7 @@
    - - - + diff --git a/apps/showcase/src/main/webapp/WEB-INF/bean-validation/bean-validation.jsp b/apps/showcase/src/main/webapp/WEB-INF/bean-validation/bean-validation.jsp index 2210b8496d..11d9c724c6 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/bean-validation/bean-validation.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/bean-validation/bean-validation.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/conversion/AddressAction.java.txt b/apps/showcase/src/main/webapp/WEB-INF/conversion/AddressAction.java.txt index 4342f8b219..c3e913b20d 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/conversion/AddressAction.java.txt +++ b/apps/showcase/src/main/webapp/WEB-INF/conversion/AddressAction.java.txt @@ -20,7 +20,7 @@ package org.apache.struts2.showcase.conversion; import java.util.LinkedHashSet; import java.util.Set; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; /** * @version $Date$ $Id$ @@ -28,15 +28,15 @@ import com.opensymphony.xwork2.ActionSupport; public class AddressAction extends ActionSupport { private Set addresses = new LinkedHashSet(); - + public Set getAddresses() { return addresses; } public void setAddresses(Set addresses) { this.addresses = addresses; } - - + + public String input() throws Exception { return SUCCESS; } - + public String submit() throws Exception { System.out.println(addresses); return SUCCESS; diff --git a/apps/showcase/src/main/webapp/WEB-INF/conversion/OperationsEnumAction.java.txt b/apps/showcase/src/main/webapp/WEB-INF/conversion/OperationsEnumAction.java.txt index 35e1175721..e2ad8d76cb 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/conversion/OperationsEnumAction.java.txt +++ b/apps/showcase/src/main/webapp/WEB-INF/conversion/OperationsEnumAction.java.txt @@ -21,28 +21,28 @@ import java.util.Arrays; import java.util.LinkedList; import java.util.List; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; /** - * + * * @version $Date$ $Id$ */ public class OperationsEnumAction extends ActionSupport { private static final long serialVersionUID = -2229489704988870318L; - + private List selectedOperations = new LinkedList(); - + public List getSelectedOperations() { return this.selectedOperations; } public void setSelectedOperations(List selectedOperations) { this.selectedOperations = selectedOperations; } - - + + public List getAvailableOperations() { return Arrays.asList(OperationsEnum.values()); } - + public String input() throws Exception { return SUCCESS; } diff --git a/apps/showcase/src/main/webapp/WEB-INF/conversion/PersonAction.java.txt b/apps/showcase/src/main/webapp/WEB-INF/conversion/PersonAction.java.txt index 1e0bd55e3a..fbbcf2dc4c 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/conversion/PersonAction.java.txt +++ b/apps/showcase/src/main/webapp/WEB-INF/conversion/PersonAction.java.txt @@ -19,24 +19,24 @@ package org.apache.struts2.showcase.conversion; import java.util.List; -import com.opensymphony.xwork2.ActionSupport; +import org.apache.struts2.ActionSupport; /** - * + * */ public class PersonAction extends ActionSupport { - + private List persons; - + public List getPersons() { return persons; } public void setPersons(List persons) { this.persons = persons; } - - - + + + public String input() throws Exception { return SUCCESS; } - + public String submit() throws Exception { return SUCCESS; } diff --git a/apps/showcase/src/main/webapp/WEB-INF/conversion/enterAddressInfo.jsp b/apps/showcase/src/main/webapp/WEB-INF/conversion/enterAddressInfo.jsp index 04eed7aec6..676c169496 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/conversion/enterAddressInfo.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/conversion/enterAddressInfo.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/conversion/enterOperations.jsp b/apps/showcase/src/main/webapp/WEB-INF/conversion/enterOperations.jsp index 803cd98905..d3e30033e9 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/conversion/enterOperations.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/conversion/enterOperations.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/conversion/enterPersonInfo.jsp b/apps/showcase/src/main/webapp/WEB-INF/conversion/enterPersonInfo.jsp index 0459d1ae3d..acb5b03773 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/conversion/enterPersonInfo.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/conversion/enterPersonInfo.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/conversion/index.jsp b/apps/showcase/src/main/webapp/WEB-INF/conversion/index.jsp index 04db6926ee..adf6569e35 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/conversion/index.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/conversion/index.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/conversion/showAddressInfo.jsp b/apps/showcase/src/main/webapp/WEB-INF/conversion/showAddressInfo.jsp index a8c8a7fdc1..3d636cb363 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/conversion/showAddressInfo.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/conversion/showAddressInfo.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/conversion/showOperations.jsp b/apps/showcase/src/main/webapp/WEB-INF/conversion/showOperations.jsp index ed8e226882..8e643539a2 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/conversion/showOperations.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/conversion/showOperations.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/conversion/showPersonInfo.jsp b/apps/showcase/src/main/webapp/WEB-INF/conversion/showPersonInfo.jsp index d4e6f7f508..d3fc85ccbf 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/conversion/showPersonInfo.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/conversion/showPersonInfo.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/date.jsp b/apps/showcase/src/main/webapp/WEB-INF/date.jsp index 400cd6d246..cde8627fe6 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/date.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/date.jsp @@ -1,2 +1,22 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/decorators.xml b/apps/showcase/src/main/webapp/WEB-INF/decorators.xml deleted file mode 100644 index f6b8bfa4e1..0000000000 --- a/apps/showcase/src/main/webapp/WEB-INF/decorators.xml +++ /dev/null @@ -1,17 +0,0 @@ - - - - - - /debug.jsp - /styles/* - /scripts/* - /images/* - /struts/* - /nodecorate/* - - - - /* - - diff --git a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp index 4c25c583be..a020e926d2 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp @@ -1,3 +1,23 @@ + <%@ page import="org.apache.struts2.result.StrutsResultSupport" %> <%@ page @@ -11,11 +31,11 @@ // Calculate the view sources url String sourceUrl = request.getContextPath() + "/viewSource.action"; - com.opensymphony.xwork2.ActionInvocation inv = com.opensymphony.xwork2.ActionContext.getContext().getActionInvocation(); + org.apache.struts2.ActionInvocation inv = org.apache.struts2.ActionContext.getContext().getActionInvocation(); org.apache.struts2.dispatcher.mapper.ActionMapping mapping = org.apache.struts2.ServletActionContext.getActionMapping(); if (inv != null) { try { - com.opensymphony.xwork2.util.location.Location loc = inv.getProxy().getConfig().getLocation(); + org.apache.struts2.util.location.Location loc = inv.getProxy().getConfig().getLocation(); sourceUrl += "?config=" + (loc != null ? loc.getURI() + ":" + loc.getLineNumber() : ""); } catch (Exception e) { sourceUrl += "?config="; @@ -29,8 +49,6 @@ sourceUrl += "?page=" + request.getServletPath(); } %> -<%@taglib prefix="decorator" uri="http://www.opensymphony.com/sitemesh/decorator" %> -<%@taglib prefix="page" uri="http://www.opensymphony.com/sitemesh/page" %> <%@taglib prefix="s" uri="/struts-tags" %> @@ -41,34 +59,43 @@ - <decorator:title default="Struts2 Showcase"/> + <sitemesh:write property="title"/> - - + + + + - - - + - - + + + + - + + jQuery(document).ready(function() { prettyPrint(); } ); + + - + - - +
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/dispatcher/dispatch-result.jsp b/apps/showcase/src/main/webapp/WEB-INF/dispatcher/dispatch-result.jsp new file mode 100644 index 0000000000..d493b146b2 --- /dev/null +++ b/apps/showcase/src/main/webapp/WEB-INF/dispatcher/dispatch-result.jsp @@ -0,0 +1,42 @@ + +<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Struts2 Showcase - Dispatcher result Example + + + + + + +
    +
    +
    + This page is a result of "dispatching" to it from an action +
    +
    +
    + + diff --git a/apps/showcase/src/main/webapp/WEB-INF/dwr.xml b/apps/showcase/src/main/webapp/WEB-INF/dwr.xml index 99869bf4ab..2837fed6dc 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/dwr.xml +++ b/apps/showcase/src/main/webapp/WEB-INF/dwr.xml @@ -1,8 +1,27 @@ - + - @@ -10,7 +29,7 @@ - + diff --git a/apps/showcase/src/main/webapp/WEB-INF/empmanager/editEmployee.jsp b/apps/showcase/src/main/webapp/WEB-INF/empmanager/editEmployee.jsp index 7518395edb..49f41b1775 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/empmanager/editEmployee.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/empmanager/editEmployee.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/empmanager/editSkill.jsp b/apps/showcase/src/main/webapp/WEB-INF/empmanager/editSkill.jsp index 71f9f83934..d4ce386776 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/empmanager/editSkill.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/empmanager/editSkill.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/empmanager/listEmployees.jsp b/apps/showcase/src/main/webapp/WEB-INF/empmanager/listEmployees.jsp index 79006e46b1..f06f7a3657 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/empmanager/listEmployees.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/empmanager/listEmployees.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/empmanager/listSkills.jsp b/apps/showcase/src/main/webapp/WEB-INF/empmanager/listSkills.jsp index 9fd2ff36aa..a1c5ac3609 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/empmanager/listSkills.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/empmanager/listSkills.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/filedownload/index.jsp b/apps/showcase/src/main/webapp/WEB-INF/filedownload/index.jsp index fa330892ce..ac1082d20d 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/filedownload/index.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/filedownload/index.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> @@ -19,7 +39,7 @@ - Download image file. + Download image file.
    @@ -27,7 +47,7 @@
    - Download ZIP file. + Download ZIP file.
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/fileupload/multiple-success.jsp b/apps/showcase/src/main/webapp/WEB-INF/fileupload/multiple-success.jsp new file mode 100644 index 0000000000..3ce6d84bb4 --- /dev/null +++ b/apps/showcase/src/main/webapp/WEB-INF/fileupload/multiple-success.jsp @@ -0,0 +1,65 @@ + +<%@ page + language="java" + contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8"%> +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Struts2 Showcase - Fileupload sample - Multiple fileupload + + + + + +
    + + + + + + + + + + + + +
    +
    + File (): +
      +
    • ContentType:
    • +
    • FileName:
    • +
    • File:
    • +
    +
    +
    +
    +
    +
    + + + \ No newline at end of file diff --git a/apps/showcase/src/main/webapp/WEB-INF/fileupload/multipleUploadUsingArray.jsp b/apps/showcase/src/main/webapp/WEB-INF/fileupload/multipleUploadUsingArray.jsp index 0756fa2047..7da56ba35c 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/fileupload/multipleUploadUsingArray.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/fileupload/multipleUploadUsingArray.jsp @@ -1,3 +1,23 @@ + <%@ page language="java" contentType="text/html; charset=UTF-8" diff --git a/apps/showcase/src/main/webapp/WEB-INF/fileupload/multipleUploadUsingList.jsp b/apps/showcase/src/main/webapp/WEB-INF/fileupload/multipleUploadUsingList.jsp index 8d8aacf8f9..a7e227364d 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/fileupload/multipleUploadUsingList.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/fileupload/multipleUploadUsingList.jsp @@ -1,4 +1,24 @@ -<%@ page + +<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%> diff --git a/apps/showcase/src/main/webapp/WEB-INF/fileupload/upload-success.jsp b/apps/showcase/src/main/webapp/WEB-INF/fileupload/upload-success.jsp index 18520178f7..e694b75b9a 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/fileupload/upload-success.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/fileupload/upload-success.jsp @@ -1,29 +1,52 @@ -<%@ page - language="java" - contentType="text/html; charset=UTF-8" - pageEncoding="UTF-8"%> + +<%@ page + language="java" + contentType="text/html; charset=UTF-8" + pageEncoding="UTF-8" %> <%@ taglib prefix="s" uri="/struts-tags" %> - Struts2 Showcase - Fileupload sample + Struts2 Showcase - Fileupload sample
    -
    -
    -
      -
    • ContentType:
    • -
    • FileName:
    • -
    • File:
    • -
    • Caption:
    • -
    -
    -
    +
    +
    +
      +
    • ContentType:
    • +
    • FileName:
    • +
    • Original FileName:
    • +
    • File:
    • +
    • Caption:
    • +
    • Size:
    • +
    • Input name:
    • +
    +
    +
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/fileupload/upload.jsp b/apps/showcase/src/main/webapp/WEB-INF/fileupload/upload.jsp index ce7ce0cce1..a806af5590 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/fileupload/upload.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/fileupload/upload.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/freemarker/customFreemarkerManagerUsage.ftl b/apps/showcase/src/main/webapp/WEB-INF/freemarker/customFreemarkerManagerUsage.ftl index e44513d50f..05f8d530c4 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/freemarker/customFreemarkerManagerUsage.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/freemarker/customFreemarkerManagerUsage.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Freemarker - CustomFreemarkerManager Usage diff --git a/apps/showcase/src/main/webapp/WEB-INF/freemarker/index.jsp b/apps/showcase/src/main/webapp/WEB-INF/freemarker/index.jsp index 360c6cb77e..948684ed9f 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/freemarker/index.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/freemarker/index.jsp @@ -1,3 +1,23 @@ + <% response.sendRedirect("/freemarker/customFreemarkerManagerDemo.action"); %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/freemarker/standardTags.ftl b/apps/showcase/src/main/webapp/WEB-INF/freemarker/standardTags.ftl index 907bec05c7..e4a14593d1 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/freemarker/standardTags.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/freemarker/standardTags.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Freemarker - Standard Struts Freemarker Tags diff --git a/apps/showcase/src/main/webapp/WEB-INF/hangman/blank.ftl b/apps/showcase/src/main/webapp/WEB-INF/hangman/blank.ftl index e69de29bb2..2ffa2ec5d1 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/hangman/blank.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/hangman/blank.ftl @@ -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. + */ +--> \ No newline at end of file diff --git a/apps/showcase/src/main/webapp/WEB-INF/hangman/hangmanNonAjax.ftl b/apps/showcase/src/main/webapp/WEB-INF/hangman/hangmanNonAjax.ftl index b3d112d764..3c32518920 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/hangman/hangmanNonAjax.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/hangman/hangmanNonAjax.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Hangman @@ -119,6 +139,7 @@ <@s.a href="%{#url}" id="%{#currentCharacter}" + > " width="36" border="0" /> diff --git a/apps/showcase/src/main/webapp/WEB-INF/hangman/updateCharacterAvailable.ftl b/apps/showcase/src/main/webapp/WEB-INF/hangman/updateCharacterAvailable.ftl index b5b000d27b..326b6b006a 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/hangman/updateCharacterAvailable.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/hangman/updateCharacterAvailable.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> <#if hangman.gameEnded()> <@s.set var="winImageName" value="%{'you-win.png'}" /> <@s.set var="looseImageName" value="%{'you-lose.png'}" /> diff --git a/apps/showcase/src/main/webapp/WEB-INF/hangman/updateGuessLeft.ftl b/apps/showcase/src/main/webapp/WEB-INF/hangman/updateGuessLeft.ftl index 22b6904004..07a969eae4 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/hangman/updateGuessLeft.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/hangman/updateGuessLeft.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> <#if (hangman.guessLeft() >= 0)> <@s.set var="guessLeftImageName" value="%{'Chalkboard_'+hangman.guessLeft()+'.png'}" /> <@s.url var="url" value="%{'/hangman/images/'+#guessLeftImageName}" /> diff --git a/apps/showcase/src/main/webapp/WEB-INF/hangman/updateScaffold.ftl b/apps/showcase/src/main/webapp/WEB-INF/hangman/updateScaffold.ftl index 24fdcffba0..ccbc551c9e 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/hangman/updateScaffold.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/hangman/updateScaffold.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> <@s.set var="scaffoldImageName" value="%{'scaffold_'+hangman.guessLeft()+'.png'}" /> <@s.url var="url" value="%{'/hangman/images/'+#scaffoldImageName}" /> " border="0"/> diff --git a/apps/showcase/src/main/webapp/WEB-INF/hangman/updateVocabCharacters.ftl b/apps/showcase/src/main/webapp/WEB-INF/hangman/updateVocabCharacters.ftl index 2abb554d0f..0df728d290 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/hangman/updateVocabCharacters.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/hangman/updateVocabCharacters.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> <#if hangman.gameEnded()> <@s.iterator var="currentCharacter" value="%{hangman.vocab.inCharacters()}" stat="stat"> <@s.url var="url" value="%{'/hangman/images/Chalkboard_'+#currentCharacter.toString()+'.png'}" /> diff --git a/apps/showcase/src/main/webapp/WEB-INF/help.jsp b/apps/showcase/src/main/webapp/WEB-INF/help.jsp index 4e43366370..96146bfd1f 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/help.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/help.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/modelDriven/modelDriven.jsp b/apps/showcase/src/main/webapp/WEB-INF/modelDriven/modelDriven.jsp index 39018c5bf8..075073ccf6 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/modelDriven/modelDriven.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/modelDriven/modelDriven.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/modelDriven/modelDrivenResult.jsp b/apps/showcase/src/main/webapp/WEB-INF/modelDriven/modelDrivenResult.jsp index 6d8e288b75..97bc75ef3a 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/modelDriven/modelDrivenResult.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/modelDriven/modelDrivenResult.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/paramsannotation.vm b/apps/showcase/src/main/webapp/WEB-INF/paramsannotation.vm new file mode 100644 index 0000000000..a0c4efefc4 --- /dev/null +++ b/apps/showcase/src/main/webapp/WEB-INF/paramsannotation.vm @@ -0,0 +1,19 @@ +#* +* Licensed to the Apache Software Foundation (ASF) under one +* or more contributor license agreements. See the NOTICE file +* distributed with this work for additional information +* regarding copyright ownership. The ASF licenses this file +* to you under the Apache License, Version 2.0 (the +* "License"); you may not use this file except in compliance +* with the License. You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, +* software distributed under the License is distributed on an +* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +* KIND, either express or implied. See the License for the +* specific language governing permissions and limitations +* under the License. +*# +
    $action.renderVarToPrint()
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/person/edit-person.jsp b/apps/showcase/src/main/webapp/WEB-INF/person/edit-person.jsp index 468848375b..a301c69c15 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/person/edit-person.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/person/edit-person.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/person/list-people.ftl b/apps/showcase/src/main/webapp/WEB-INF/person/list-people.ftl index 082134b9a3..88ededf7c0 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/person/list-people.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/person/list-people.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Person Manager Example - All People @@ -31,9 +51,9 @@ <#list people as person> - ${person.id?html} - ${person.name?html} - ${person.lastName?html} + ${person.id} + ${person.name} + ${person.lastName} diff --git a/apps/showcase/src/main/webapp/WEB-INF/person/new-person.ftl b/apps/showcase/src/main/webapp/WEB-INF/person/new-person.ftl index 25d2dbc69e..07a66d4a6f 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/person/new-person.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/person/new-person.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Person Manager Example - New Person diff --git a/apps/showcase/src/main/webapp/WEB-INF/showcase.jsp b/apps/showcase/src/main/webapp/WEB-INF/showcase.jsp index adb38464d2..92c1bfd60d 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/showcase.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/showcase.jsp @@ -1,4 +1,24 @@ -<%-- + +<%-- showcase.jsp @version $Date$ $Id$ @@ -19,7 +39,7 @@

    Welcome!

    The Struts Showcase demonstrates a variety of use cases and tag usages. Essentially, the application exercises various framework features in isolation. The Showcase is not meant as a "best practices" example.

    -

    For more "by example" solutions, see the Struts Cookbook » pages.

    +

    For more "by example" solutions, see the Struts Examples » pages.

    diff --git a/apps/showcase/src/main/webapp/WEB-INF/sitemesh-decorator.tld b/apps/showcase/src/main/webapp/WEB-INF/sitemesh-decorator.tld deleted file mode 100644 index 18f525c6ea..0000000000 --- a/apps/showcase/src/main/webapp/WEB-INF/sitemesh-decorator.tld +++ /dev/null @@ -1,79 +0,0 @@ - - - - - - 1.0 - 1.1 - SiteMesh Decorator Tags - sitemesh-decorator - - - head - com.opensymphony.module.sitemesh.taglib.decorator.HeadTag - JSP - - - - body - com.opensymphony.module.sitemesh.taglib.decorator.BodyTag - JSP - - - - title - com.opensymphony.module.sitemesh.taglib.decorator.TitleTag - JSP - - default - false - true - - - - - getProperty - com.opensymphony.module.sitemesh.taglib.decorator.PropertyTag - JSP - - property - true - true - - - default - false - true - - - writeEntireProperty - false - true - - - - - usePage - com.opensymphony.module.sitemesh.taglib.decorator.UsePageTag - com.opensymphony.module.sitemesh.taglib.decorator.UsePageTEI - JSP - - id - true - false - - - - - useHtmlPage - com.opensymphony.module.sitemesh.taglib.decorator.UsePageTag - com.opensymphony.module.sitemesh.taglib.decorator.UseHTMLPageTEI - JSP - - id - true - false - - - - \ No newline at end of file diff --git a/apps/showcase/src/main/webapp/WEB-INF/sitemesh-page.tld b/apps/showcase/src/main/webapp/WEB-INF/sitemesh-page.tld deleted file mode 100644 index 797ec5d618..0000000000 --- a/apps/showcase/src/main/webapp/WEB-INF/sitemesh-page.tld +++ /dev/null @@ -1,95 +0,0 @@ - - - - - - 1.0 - 1.1 - SiteMesh Page Tags - sitemesh-page - - - applyDecorator - com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag - JSP - - name - false - true - - - page - false - true - - - title - false - true - - - id - false - true - - - contentType - false - true - - - encoding - false - true - - - - - - apply-decorator - com.opensymphony.module.sitemesh.taglib.page.ApplyDecoratorTag - JSP - - name - false - true - - - page - false - true - - - title - false - true - - - id - false - true - - - contentType - false - true - - - encoding - false - true - - - - - param - com.opensymphony.module.sitemesh.taglib.page.ParamTag - JSP - - name - false - true - - - - \ No newline at end of file diff --git a/apps/showcase/src/main/webapp/WEB-INF/sitemesh.xml b/apps/showcase/src/main/webapp/WEB-INF/sitemesh.xml deleted file mode 100644 index 35d70168cd..0000000000 --- a/apps/showcase/src/main/webapp/WEB-INF/sitemesh.xml +++ /dev/null @@ -1,54 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/apps/showcase/src/main/webapp/WEB-INF/sitemesh3.xml b/apps/showcase/src/main/webapp/WEB-INF/sitemesh3.xml new file mode 100644 index 0000000000..88cd74843d --- /dev/null +++ b/apps/showcase/src/main/webapp/WEB-INF/sitemesh3.xml @@ -0,0 +1,30 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/actionPrefix.ftl b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/actionPrefix.ftl index 0faa3a9e83..6e4432ea53 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/actionPrefix.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/actionPrefix.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Non UI Tags - Action Prefix (Freemarker) @@ -13,7 +33,7 @@

    You have come to this page because you used an action prefix.

    -

    The text you've entered is ${text!''?html}

    +

    The text you've entered is ${text!''}

    <@s.a href="javascript:history.back();" cssClass="btn btn-info"> Back diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl index cc09ac8256..98b0a92324 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Non UI Tags - Action Prefix (Freemarker) diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/methodPrefix.ftl b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/methodPrefix.ftl index 744f7fa3fb..e2cf0ee56c 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/methodPrefix.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/methodPrefix.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Non UI Tags - Action Prefix (Freemarker) @@ -12,8 +32,8 @@

    You have come to this page because you used an method prefix.

    - -

    The text you've enter is ${text!''?html}

    + +

    The text you've enter is ${text!''}

    <@s.a href="javascript:history.back();" cssClass="btn btn-info"> Back

    diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/normalSubmit.ftl b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/normalSubmit.ftl index dd15b0827f..7df58271df 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/normalSubmit.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/normalSubmit.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Non UI Tags - Action Prefix (Freemarker) @@ -12,7 +32,7 @@

    You have come to this page because you did a normal submit.

    - +

    The text you've enter is %{text}

    <@s.a href="javascript:history.back();" cssClass="btn btn-info"> Back diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/redirectActionPrefix.ftl b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/redirectActionPrefix.ftl index 4dd06d7d12..93fee964c1 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/redirectActionPrefix.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionPrefix/redirectActionPrefix.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Non UI Tags - Action Prefix (Freemarker) @@ -12,11 +32,11 @@

    You have come to this page because you used an 'redirect-action' prefix.

    - +

    Because this is a redirect-action, the text will be lost, due to a redirection implies a new request being issued from the client.

    - The text you've enter is ${text!''?html}

    + The text you've enter is ${text!''}

    <@s.a href="javascript:history.back();" cssClass="btn btn-info"> Back

    diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage.jsp index abfa2535b0..486d6e0074 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage.jsp @@ -1 +1,21 @@ +

    This is INCLUDED by the action tag

    diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage2.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage2.jsp index 6cdc04055a..50c6e0881b 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage2.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage2.jsp @@ -1,2 +1,21 @@ - +

    This is INCLUDED by the action tag (Page2)

    diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage3.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage3.jsp index 4ebbcc744f..fa7071393e 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage3.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/includedPage3.jsp @@ -1,2 +1,21 @@ - +

    This is INCLUDED by the action tag (Page3)

    diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp index 1ddda5a5cf..d81ce94018 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/date.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/date.jsp index 315f12a29d..570a46ef20 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/date.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/date.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/debug.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/debug.jsp index 0294533304..1629bf3ab5 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/debug.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/debug.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/ifTag/testIf.ftl b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/ifTag/testIf.ftl index 340df6f457..88cc62a55f 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/ifTag/testIf.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/ifTag/testIf.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Non Ui Tag - Test If Tag (Freemarker) diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/ifTag/testIf.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/ifTag/testIf.jsp index 6fa99cb0a1..f9fe499971 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/ifTag/testIf.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/ifTag/testIf.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp index 0076d9f15e..c2c7ff3dd4 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp index 49f74f5ce2..f4a31d897a 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp index c79a232332..1798da4457 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showAppendIteratorTagDemo.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showAppendIteratorTagDemo.jsp index 5120e01907..f625216e6d 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showAppendIteratorTagDemo.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showAppendIteratorTagDemo.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp index 720b38ddb1..079c2fa476 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showMergeIteratorTagDemo.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showMergeIteratorTagDemo.jsp index 692dd9f65c..52ab3330ea 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showMergeIteratorTagDemo.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/showMergeIteratorTagDemo.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemo.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemo.jsp index 7cffab1f14..37836430d2 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemo.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemo.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp index 47bbbefc72..e704e577d8 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/actionTagExampleCalled.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/actionTagExampleCalled.jsp index c97dc675a5..214ad6b92a 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/actionTagExampleCalled.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/actionTagExampleCalled.jsp @@ -1,2 +1,22 @@ + <%@taglib prefix="s" uri="/struts-tags" %> This text is from the called class \ No newline at end of file diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/actionTagExampleCalling.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/actionTagExampleCalling.jsp index 762a0d490b..07a4ae48c6 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/actionTagExampleCalling.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/actionTagExampleCalling.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/componentTagExample.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/componentTagExample.jsp index 232f9e5a5b..97711e4284 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/componentTagExample.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/componentTagExample.jsp @@ -1,68 +1,88 @@ + <%@taglib prefix="s" uri="/struts-tags" %> - Struts2 Showcase - UI Tags - Component Tag - + Struts2 Showcase - UI Tags - Component Tag +
    -
    -
    -

    This example tries to demonstrates the usage of <s:component ... > tag.

    +

    +
    +

    This example tries to demonstrate the usage of <s:component ... > tag.

    -

    To have a look at the source of this jsp page click - - here -

    +

    To have a look at the source of this jsp page click + + here +

    - Example 1: -

    This example load the template from the webapp context path using - the default (ftl) as its template. - - - -

    + Example 1: +

    This example load the template from the webapp context path using + the default (ftl) as its template. + + + +

    - Example 2: -

    This example load the template from the webapp context path using - jsp as its template (notice the *.jsp extension to the template). - - - -

    + Example 2: +

    This example load the template from the webapp context path using + jsp as its template (notice the *.jsp extension to the template). + + + +

    - Example 3 -

    This example load the template from the webapp context path, - using the default template directory and theme (default to - 'template' and 'xhtml' respectively) - - - -

    + Example 3 +

    This example load the template from the webapp context path, + using the default template directory and theme (default to + 'template' and 'xhtml' respectively) + + + +

    - Example 4 -

    This example load the template from the webapp classpath using - a custom themplate directory and theme. - - - -

    -

    -
    + Example 4 +

    This example load the template from the webapp classpath using + a custom themplate directory and theme. + + + +

    +
    +
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/dynamicTreeSelect.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/dynamicTreeSelect.jsp index 2c1cd2e07b..c779da6423 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/dynamicTreeSelect.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/dynamicTreeSelect.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> Id:
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/example.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/example.jsp index 847b794a9d..923e4c6240 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/example.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/example.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> @@ -18,7 +38,7 @@ - + @@ -94,8 +114,8 @@ emptyOption="true" /> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/example.vm b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/example.vm index cd6978ea0f..c7ca9312cb 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/example.vm +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/example.vm @@ -1,3 +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. +*# Struts2 Showcase - UI Tags Example (Velocity) @@ -13,16 +31,20 @@
    #sform ("action=exampleSubmitVelocity" "method=post" "enctype=multipart/form-data") - #stextfield ("label=Name" "name=name") - #stextarea ("label=Biography" "name=bio" "cols=20" "rows=3") - #sselect ("label=Favourite Color" "list={'Red', 'Blue', 'Green'}" "name=favouriteColor" "emptyOption=true" "headerKey=None" "headerValue=None") - #sselect ("label=Favourite Language" "list=favouriteLanguages" "name=favouriteLanguage" "listKey=key" "listValue=description" "emptyOption=true" "headerKey=None" "headerValue=None") - #scheckboxlist ("label=Friends" "list={'Patrick', 'Jason', 'Jay', 'Toby', 'Rene'}" "name=friends") - #scheckbox ("label=Age 18+" "name=legalAge") - #sdoubleselect ("label=State" "name=region" "list={'North', 'South'}" "value='North'" "doubleValue='Florida'" "doubleList=top == 'North' ? {'Oregon', 'Washington'} : {'Texas', 'Florida'}" "doubleName=state" "headerKey=-1" "headerValue=---------- Please Select ----------" "emptyOption=true" ) - #sdoubleselect ("label=Favourite Vehical" "name=favouriteVehicalType" "list=vehicalTypeList" "listKey=key" "listValue=description" "value='MotorcycleKey'" "doubleValue='YamahaKey'" "doubleList=vehicalSpecificList" "doubleListKey=key" "doubleListValue=description" "doubleName=favouriteVehicalSpecific" "headerKey=-1" "headerValue=---------- Please Select ----------" "emptyOption=true" ) - #sfile ("label=Picture" "name=picture") - #soptiontransferselect ("label=Favourite Cartoons Characters" "name=leftSideCartoonCharacters" "leftTitle=Left Title" "rightTitle=Right Title" "list={'Popeye', 'He-Man', 'Spiderman'}" "multiple=true" "headerKey=headerKey" "headerValue=--- Please Select ---" "emptyOption=true" "doubleList={'Superman', 'Mickey Mouse', 'Donald Duck'}" "doubleName=rightSideCartoonCharacters" "doubleHeaderKey=doubleHeaderKey" "doubleHeaderValue=--- Please Select ---" "doubleEmptyOption=true" "doubleMultiple=true" ) + #stextfield ("label=Name" "name=name" "tooltip=Enter your Name here") + #stextfield ("label=Birthday" "name=birthday" "tooltip=Select Your Birthday") + #stextfield ("label=Wake up time" "name=wakeup" "tooltip=Enter the time you wake up") + #stextarea ("label=Biography" "name=bio" "tooltip=Enter your Biography" "cols=20" "rows=3") + #sselect ("label=Favourite Color" "tooltip=Choose Your Favourite Color" "list={'Red', 'Blue', 'Green'}" "name=favouriteColor" "emptyOption=true" "headerKey=None" "headerValue=None") + #sselect ("label=Favourite Language" "tooltip=Choose Your Favourite Language" "list=favouriteLanguages" "name=favouriteLanguage" "listKey=key" "listValue=description" "emptyOption=true" "headerKey=None" "headerValue=None") + #scheckboxlist ("label=Friends" "tooltip=Choose your Friends" "list={'Wes', 'Patrick', 'Jason', 'Jay', 'Toby', 'Rene'}" "name=friends") + #sradio ("label=Best Friend" "tooltip=Choose your Best Friend" "list={'Wes', 'Patrick', 'Jason', 'Jay', 'Toby', 'Rene'}" "name=bestFriend" "cssErrorClass=foo") + #scheckbox ("label=Age 18+" "name=legalAge" "tooltip=Confirm that you are Over 18") + #sdoubleselect ("label=State" "name=region" "tooltip=Choose Your State" "list={'North', 'South'}" "value='North'" "doubleValue='Florida'" "doubleList=top == 'North' ? {'Oregon', 'Washington'} : {'Texas', 'Florida'}" "doubleName=state" "headerKey=-1" "headerValue=---------- Please Select ----------" "emptyOption=true" ) + #sdoubleselect ("label=Favourite Vehicle" "name=favouriteVehicalType" "tooltip=Choose your Vehicle" "list=vehicalTypeList" "listKey=key" "listValue=description" "value='MotorcycleKey'" "doubleValue='YamahaKey'" "doubleList=vehicalSpecificList" "doubleListKey=key" "doubleListValue=description" "doubleName=favouriteVehicalSpecific" "headerKey=-1" "headerValue=---------- Please Select ----------" "emptyOption=true" ) + #sfile ("label=Picture" "name=picture" "tooltip=Upload Your Picture") + #soptiontransferselect ("label=Favourite Cartoon Characters" "name=leftSideCartoonCharacters" "tooltip=Select Your Favourite Cartoon Characters" "leftTitle=Left Title" "rightTitle=Right Title" "list={'Popeye', 'He-Man', 'Spiderman'}" "multiple=true" "headerKey=headerKey" "headerValue=--- Please Select ---" "emptyOption=true" "doubleList={'Superman', 'Mickey Mouse', 'Donald Duck'}" "doubleName=rightSideCartoonCharacters" "doubleHeaderKey=doubleHeaderKey" "doubleHeaderValue=--- Please Select ---" "doubleEmptyOption=true" "doubleMultiple=true" ) + #stextarea ("label=Your Thoughts" "name=thoughts" "tooltip=Enter your thoughts here" "cols=20" "rows=3") #ssubmit("cssClass=btn btn-primary") #sreset("cssClass=btn btn-danger") #end diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/exampleSubmited.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/exampleSubmited.jsp index cba7fc2bab..ac87d1d8b1 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/exampleSubmited.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/exampleSubmited.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> @@ -16,8 +36,8 @@ - - + + @@ -30,22 +50,24 @@ - - + + - - + + - - + + diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/exampleSubmited.vm b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/exampleSubmited.vm index 9f69944f45..e159bef17a 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/exampleSubmited.vm +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/exampleSubmited.vm @@ -1,3 +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. +*# Struts2 Showcase - UI Tags Example (Velocity) - Example Submited @@ -15,41 +33,45 @@ #slabel ("label=Name" "name=name") #slabel ("label=Birthday" "name=birthday") - - + + #sdate ("name=wakeup" "format=hh:mm aa") #slabel ("label=Biography" "name=bio") #slabel ("label=Favourite Color" "name=favouriteColor") #slabel ("label=Friends" "name=friends") + #slabel ("label=Best Friend" "name=bestFriend") #slabel ("label=Legal Age" "name=legalAge") #slabel ("label=Region" "name=region") #slabel ("label=State" "name=state") #slabel ("label=Picture" "name=picture") #slabel ("label=Favourite Language" "name=favouriteLanguage") - #slabel ("label=Favourite Vehical Type" "name=favouriteVehicalType") - #slabel ("label=Favourite Vehical Specific" "name=favouriteVehicalSpecific") + #slabel ("label=Favourite Vehicle Type" "name=favouriteVehicalType") + #slabel ("label=Favourite Vehicle Specific" "name=favouriteVehicalSpecific") - Favourite Cartoon Characters (Left): - + + - Favourite Cartoon Characters (Right): - + + + #slabel ("label=Thoughts" "name=thoughts")
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/lotsOfOptiontransferselect.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/lotsOfOptiontransferselect.jsp index 5ce4cd454e..93a15cb49f 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/lotsOfOptiontransferselect.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/lotsOfOptiontransferselect.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/lotsOfOptiontransferselectSubmit.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/lotsOfOptiontransferselectSubmit.jsp index 0756978a88..dccf8da690 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/lotsOfOptiontransferselectSubmit.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/lotsOfOptiontransferselectSubmit.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> @@ -90,7 +110,7 @@ Non Favourite Sports: - + .  diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/moreSelects.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/moreSelects.jsp index e1aa12574f..5a7314ab49 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/moreSelects.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/moreSelects.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/moreSelectsSubmit.jsp b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/moreSelectsSubmit.jsp index c17a2d7642..3d04b61e3b 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tags/ui/moreSelectsSubmit.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tags/ui/moreSelectsSubmit.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tiles.xml b/apps/showcase/src/main/webapp/WEB-INF/tiles.xml index a74de1b6b9..e0ddd5f0f8 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tiles.xml +++ b/apps/showcase/src/main/webapp/WEB-INF/tiles.xml @@ -1,4 +1,4 @@ - + diff --git a/apps/showcase/src/main/webapp/WEB-INF/tiles/body.ftl b/apps/showcase/src/main/webapp/WEB-INF/tiles/body.ftl index 73b2559ee9..3ca1f9704d 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tiles/body.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/tiles/body.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +-->
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/tiles/body.jsp b/apps/showcase/src/main/webapp/WEB-INF/tiles/body.jsp index 855a89688b..f8a6c15ac3 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tiles/body.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tiles/body.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %>
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/tiles/header.jsp b/apps/showcase/src/main/webapp/WEB-INF/tiles/header.jsp index d98f0010a9..283d062767 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tiles/header.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tiles/header.jsp @@ -1,3 +1,23 @@ + diff --git a/apps/showcase/src/main/webapp/WEB-INF/tiles/layout-annotations.jsp b/apps/showcase/src/main/webapp/WEB-INF/tiles/layout-annotations.jsp index 5609cb1a16..bd6542c192 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tiles/layout-annotations.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tiles/layout-annotations.jsp @@ -1,3 +1,23 @@ + <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %> <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tiles/layout.ftl b/apps/showcase/src/main/webapp/WEB-INF/tiles/layout.ftl index 9ce5915b56..387e3c930d 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tiles/layout.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/tiles/layout.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> <#assign tiles=JspTaglibs["http://tiles.apache.org/tags-tiles"]> <@tiles.importAttribute name="title" scope="request"/> diff --git a/apps/showcase/src/main/webapp/WEB-INF/tiles/layout.jsp b/apps/showcase/src/main/webapp/WEB-INF/tiles/layout.jsp index 964d014a84..0079036420 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/tiles/layout.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/tiles/layout.jsp @@ -1,3 +1,23 @@ + <%@ taglib uri="http://tiles.apache.org/tags-tiles" prefix="tiles" %> <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/token/doublePost.jsp b/apps/showcase/src/main/webapp/WEB-INF/token/doublePost.jsp index 66439b4d4a..62d442010d 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/token/doublePost.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/token/doublePost.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/token/example1.jsp b/apps/showcase/src/main/webapp/WEB-INF/token/example1.jsp index b4e3093df6..f52fbc0fd9 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/token/example1.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/token/example1.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/token/example2.jsp b/apps/showcase/src/main/webapp/WEB-INF/token/example2.jsp index 93b1f5c07b..48b9d0a7d2 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/token/example2.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/token/example2.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/token/example3.jsp b/apps/showcase/src/main/webapp/WEB-INF/token/example3.jsp index 9bfd1b66bc..d333852bb0 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/token/example3.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/token/example3.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/token/example4.ftl b/apps/showcase/src/main/webapp/WEB-INF/token/example4.ftl index 56ea4649ba..19dac0114d 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/token/example4.ftl +++ b/apps/showcase/src/main/webapp/WEB-INF/token/example4.ftl @@ -1,3 +1,23 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +--> Struts2 Showcase - Token Examples - Example 4 @@ -30,7 +50,7 @@ <@s.form action="transfer4"> <@s.token/> - <@s.textfield label="Amount" name="amount" required="true" value="400"/> + <@s.textfield label="Amount" name="amount" required=true value="400"/> <@s.submit value="Transfer money" cssClass="btn btn-primary"/>
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/token/transferDone.jsp b/apps/showcase/src/main/webapp/WEB-INF/token/transferDone.jsp index b1606e003a..17ba62dfd8 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/token/transferDone.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/token/transferDone.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation.xml b/apps/showcase/src/main/webapp/WEB-INF/validation.xml index 2849753649..db6104b086 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation.xml +++ b/apps/showcase/src/main/webapp/WEB-INF/validation.xml @@ -1,5 +1,24 @@ - - + + diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp index da07ff1085..cf8fddaeb5 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmit.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> @@ -52,7 +72,7 @@
    - + diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmitSuccess.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmitSuccess.jsp index f8a07312b2..f7d1cdcecd 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmitSuccess.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/ajaxFormSubmitSuccess.jsp @@ -1,3 +1,23 @@ + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/clientSideValidationExample.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/clientSideValidationExample.jsp index 0ac640b72e..6f2d9c0079 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/clientSideValidationExample.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/clientSideValidationExample.jsp @@ -1,3 +1,23 @@ + <%-- fieldValidatorExample.jsp diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/fieldValidatorsExample.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/fieldValidatorsExample.jsp index 4e92f0d359..198c97d770 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/fieldValidatorsExample.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/fieldValidatorsExample.jsp @@ -1,4 +1,24 @@ -<%-- + +<%-- fieldValidatorExample.jsp @author tm_jee diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/nonFieldValidatorsExample.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/nonFieldValidatorsExample.jsp index fbee116065..df55c568a0 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/nonFieldValidatorsExample.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/nonFieldValidatorsExample.jsp @@ -1,4 +1,24 @@ -<%-- + +<%-- nonFieldValidatorsExample.jsp @author tm_jee diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-basic.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-basic.jsp index d64a478ede..6c6beaa41c 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-basic.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-basic.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-client-css.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-client-css.jsp index 2224f6e56f..2f45a6f1e7 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-client-css.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-client-css.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-client.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-client.jsp index b08cc742e0..78a2d91159 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-client.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-client.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-success.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-success.jsp index 3bbb162b9f..376edd7374 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-success.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/quiz-success.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestCancel.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestCancel.jsp index cbd70a50cf..c98b835e1c 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestCancel.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestCancel.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestExample.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestExample.jsp index e33d954183..1e68126247 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestExample.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestExample.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestOk.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestOk.jsp index 6cc4918e61..d35725dbfb 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestOk.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/storeErrorsAcrossRequestOk.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/successClientSideValidationExample.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/successClientSideValidationExample.jsp index dc683e9dc8..7eda5ab4d1 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/successClientSideValidationExample.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/successClientSideValidationExample.jsp @@ -1,3 +1,23 @@ + <%-- successFieldValidatorsExample.jsp diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/successFieldValidatorsExample.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/successFieldValidatorsExample.jsp index 28358b2a5d..62135b1a24 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/successFieldValidatorsExample.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/successFieldValidatorsExample.jsp @@ -1,3 +1,23 @@ + <%-- successFieldValidatorsExample.jsp diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/successNonFieldValidatorsExample.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/successNonFieldValidatorsExample.jsp index e397c757f6..3ce13450b2 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/successNonFieldValidatorsExample.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/successNonFieldValidatorsExample.jsp @@ -1,3 +1,23 @@ + <%-- successNonFieldValidatorsExample.jsp diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/successVisitorValidatorsExample.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/successVisitorValidatorsExample.jsp index 06c1bb762e..dd7affe2da 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/successVisitorValidatorsExample.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/successVisitorValidatorsExample.jsp @@ -1,4 +1,24 @@ -<%-- + +<%-- successVisitorValidatorsExample.jsp @author tm_jee diff --git a/apps/showcase/src/main/webapp/WEB-INF/validation/visitorValidatorsExample.jsp b/apps/showcase/src/main/webapp/WEB-INF/validation/visitorValidatorsExample.jsp index 0e2f5ae4ba..eda81b8a6f 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/validation/visitorValidatorsExample.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/validation/visitorValidatorsExample.jsp @@ -1,4 +1,24 @@ -<%-- + +<%-- visitorValidatorsExample.jsp @author tm_jee diff --git a/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp b/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp index cca0b0526b..61bb6fc878 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/viewSource.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> @@ -6,49 +26,46 @@
    -
    -
    -

    View Sources

    +
    +
    +

    View Sources

    - + -
    -
    -

    -
    -						
    +            
    +
    +

    +
    
     
    -					
    -
    -
    -

    -
    -						
    +                    
    +
    +
    +

    +
    
     
    -					
    -
    -
    -

    -
    -						
    +                    
    +
    +
    +

    +
    
     
    -					
    -
    -
    -
    -
    + +
    +
    +
    +
    - + + $('#codeTab a').click(function (e) { + e.preventDefault(); + $(this).tab('show'); + }) + diff --git a/apps/showcase/src/main/webapp/WEB-INF/wait/complete.jsp b/apps/showcase/src/main/webapp/WEB-INF/wait/complete.jsp index 2b672d2719..47cbb06749 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/wait/complete.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/wait/complete.jsp @@ -1,25 +1,46 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> - Struts2 Showcase - Execute and Wait Examples - Complete + Struts2 Showcase - Execute and Wait Examples - Complete
    -
    -
    +
    +
    - We have processed your request. -

    - Click here to return. +

    We have processed your request.
    -
    -
    + + Click here to return + +
    +
    diff --git a/apps/showcase/src/main/webapp/WEB-INF/wait/example1.jsp b/apps/showcase/src/main/webapp/WEB-INF/wait/example1.jsp index b8d1702c27..2a0adaa410 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/wait/example1.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/wait/example1.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/wait/example2.jsp b/apps/showcase/src/main/webapp/WEB-INF/wait/example2.jsp index e951ddc2b6..270ff0aad6 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/wait/example2.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/wait/example2.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/wait/example3.jsp b/apps/showcase/src/main/webapp/WEB-INF/wait/example3.jsp index 35210574b8..4549b62873 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/wait/example3.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/wait/example3.jsp @@ -1,3 +1,23 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/WEB-INF/wait/index.jsp b/apps/showcase/src/main/webapp/WEB-INF/wait/index.jsp new file mode 100644 index 0000000000..b0d10cd1c5 --- /dev/null +++ b/apps/showcase/src/main/webapp/WEB-INF/wait/index.jsp @@ -0,0 +1,53 @@ + +<%@ taglib prefix="s" uri="/struts-tags" %> + + + Struts2 Showcase - Execute and Wait Examples + + + + + +
    +
    +
    + +

    + These examples illustrate Struts build in support for execute and wait. +

    +

    + When you have a process that takes a long time your users can be impatient and starts to submit/click + again. +
    A good solution is to show the user a progress page (wait page) while the process takes it time. +

    + +
    +
    Example 1 (no delay) +
    Example 2 (with delay) +
    Example 3 (with longer check delay) +

    +
    +
    + + diff --git a/apps/showcase/src/main/webapp/WEB-INF/wait/wait.jsp b/apps/showcase/src/main/webapp/WEB-INF/wait/wait.jsp index 309649df4c..57f169d87c 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/wait/wait.jsp +++ b/apps/showcase/src/main/webapp/WEB-INF/wait/wait.jsp @@ -1,53 +1,53 @@ + <%@ taglib prefix="s" uri="/struts-tags" %> - Struts2 Showcase - Execute and Wait Examples - Wait + Struts2 Showcase - Execute and Wait Examples - Wait + "/>
    -
    -
    - -

    - We are processing your request. Please wait. -

    - -
    -
    -
    - -

    - You can click this link to ">refresh. - - We have processed your request. -

    - Click here to return. - -

    -
    +
    +
    + +

    + We are processing your request. Please wait. +

    + +
    +
    +
    + +
    + You can click this link to ">refresh. +
    +
    +
    - -<%@ taglib prefix="s" uri="/struts-tags" %> - - - "/> - - - -

    - We are processing your request. Please wait. -

    - -

    - You can click this link to ">refresh. - - - diff --git a/apps/showcase/src/main/webapp/WEB-INF/web.xml b/apps/showcase/src/main/webapp/WEB-INF/web.xml index 5b7f48aaaa..490e8b3e67 100644 --- a/apps/showcase/src/main/webapp/WEB-INF/web.xml +++ b/apps/showcase/src/main/webapp/WEB-INF/web.xml @@ -1,40 +1,80 @@ - + + Struts Showcase Application - + + + async + org.apache.struts2.showcase.async.AsyncFilter + true + + struts-prepare org.apache.struts2.dispatcher.filter.StrutsPrepareFilter + true struts-execute org.apache.struts2.dispatcher.filter.StrutsExecuteFilter + true + + sitemesh3 + org.sitemesh.config.ConfigurableSiteMeshFilter + true + - - sitemesh - com.opensymphony.sitemesh.webapp.SiteMeshFilter - + + async + /async/* + struts-prepare /* + FORWARD + REQUEST - sitemesh + sitemesh3 /* + FORWARD + REQUEST struts-execute /* + FORWARD + REQUEST @@ -46,35 +86,34 @@ org.apache.struts2.tiles.StrutsTilesListener - + - - org.apache.struts2.showcase.chat.ChatSessionListener - + + org.apache.struts2.showcase.chat.ChatSessionListener + org.apache.struts2.dispatcher.listener.StrutsListener - - - dwr - uk.ltd.getahead.dwr.DWRServlet - - debug - true - + JspSupportServlet + org.apache.struts2.views.JspSupportServlet + 1 - - JspSupportServlet - org.apache.struts2.views.JspSupportServlet - 1 - - + + strutsServlet + org.apache.struts2.dispatcher.servlet.StrutsServlet + 2 + true + + + + - - dwr - /dwr/* - + + testServlet + org.apache.struts2.showcase.servlet.TestServlet + - + - + + strutsServlet + /async/receiveNewMessages + + + + testServlet + /testServlet/* + <%@taglib prefix="s" uri="/struts-tags" %> diff --git a/apps/showcase/src/main/webapp/async/index.html b/apps/showcase/src/main/webapp/async/index.html new file mode 100644 index 0000000000..3d1d74b1a2 --- /dev/null +++ b/apps/showcase/src/main/webapp/async/index.html @@ -0,0 +1,120 @@ + + + + Struts2 Showcase - Async Example + + + + +

    + + + +
    +
    +
    + +

    + These examples illustrate Struts build in support for async request processing. +

    +

    + When you have a process that takes a long time, it can make your app not scalable under heavy load conditions. + Scalability limitations include running out of memory or exhausting the pool of container threads. + To create scalable web applications, you must ensure that no threads associated with a request + are sitting idle, so the container can use them to process new requests. + Asynchronous processing refers to assigning these blocking operations to a new thread and returning + the thread associated with the request immediately to the container. +
    Reference: Asynchronous Processing +
    An interesting and vital use case for the async request processing is server push. + A good solution is to use the Servlet 3.0+ asynchronous feature. +

    + +
    +

    Example: A minimal chat room using server push

    +

    Open current page in different tabs, browsers and computers then send messages.

    +

    This is a minimal chat room which uses server push to retrieve new messages. + It doesn't poll the server frequently to check if a new message is available to display. + Instead it waits for the server to push back new messages. This approach has two obvious advantages: + low-lag communication without requests being sent, and no waste of server resources and network bandwidth.

    +
    Reference: + Asynchronous processing support in Servlet 3.0
    +
    +
    + + +
    +
    +
    +
    + + diff --git a/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl b/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl index 4152334439..cd3fc6b03a 100644 --- a/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl +++ b/apps/showcase/src/main/webapp/customTemplateDir/customTheme/ftlCustomTemplate.ftl @@ -1,7 +1,27 @@ +<#-- +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +-->

    Freemarker Custom Template - -parameter 'paramName' - ${parameters.paramName} +parameter 'paramName' - ${attributes.paramName}

    diff --git a/apps/showcase/src/main/webapp/customTemplateDir/customTheme/jspCustomTemplate.jsp b/apps/showcase/src/main/webapp/customTemplateDir/customTheme/jspCustomTemplate.jsp index 311c329877..68de034eb5 100644 --- a/apps/showcase/src/main/webapp/customTemplateDir/customTheme/jspCustomTemplate.jsp +++ b/apps/showcase/src/main/webapp/customTemplateDir/customTheme/jspCustomTemplate.jsp @@ -1,8 +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. +*/ +--%> <%@taglib prefix="s" uri="/struts-tags" %>

    -JSP Custom Template - -parameter 'paramName' - +JSP Custom Template - +parameter 'paramName' -

    diff --git a/apps/showcase/src/main/webapp/index.html b/apps/showcase/src/main/webapp/index.html index 402dd76e83..13f3b97b0e 100644 --- a/apps/showcase/src/main/webapp/index.html +++ b/apps/showcase/src/main/webapp/index.html @@ -1,3 +1,23 @@ + diff --git a/apps/showcase/src/main/webapp/person/index.html b/apps/showcase/src/main/webapp/person/index.html index bc92398268..67eafbd674 100644 --- a/apps/showcase/src/main/webapp/person/index.html +++ b/apps/showcase/src/main/webapp/person/index.html @@ -1,3 +1,23 @@ + diff --git a/apps/showcase/src/main/webapp/skill/index.html b/apps/showcase/src/main/webapp/skill/index.html index fd100664c9..e873e20ae8 100644 --- a/apps/showcase/src/main/webapp/skill/index.html +++ b/apps/showcase/src/main/webapp/skill/index.html @@ -1,3 +1,23 @@ + diff --git a/apps/showcase/src/main/webapp/template/xhtml/mytemplate.jsp b/apps/showcase/src/main/webapp/template/xhtml/mytemplate.jsp index 7ebb967817..f7c52b8e45 100644 --- a/apps/showcase/src/main/webapp/template/xhtml/mytemplate.jsp +++ b/apps/showcase/src/main/webapp/template/xhtml/mytemplate.jsp @@ -1,9 +1,28 @@ - + <%@taglib prefix="s" uri="/struts-tags" %>

    JSP Custom Template - -parameter 'paramName' - +parameter 'paramName' -

    diff --git a/apps/showcase/src/main/webapp/token/index.html b/apps/showcase/src/main/webapp/token/index.html index b224dd7caa..9ff2bc6c88 100644 --- a/apps/showcase/src/main/webapp/token/index.html +++ b/apps/showcase/src/main/webapp/token/index.html @@ -1,3 +1,23 @@ + Struts2 Showcase - Token Examples (double post) diff --git a/apps/showcase/src/main/webapp/wait/index.html b/apps/showcase/src/main/webapp/wait/index.html deleted file mode 100644 index 08cb153f78..0000000000 --- a/apps/showcase/src/main/webapp/wait/index.html +++ /dev/null @@ -1,33 +0,0 @@ - - - Struts2 Showcase - Execute and Wait Examples - - - - - - - -
    -
    -
    - -

    - These examples illustrate Struts build in support for execute and wait. -

    -

    - When you have a process that takes a long time your users can be impatient and starts to submit/click again. -
    A good solution is to show the user a progress page (wait page) while the process takes it time. -

    - -
    -
    Example 1 (no delay) -
    Example 2 (with delay) -
    Example 3 (with longer check delay) -

    -
    -
    - - diff --git a/apps/showcase/src/main/webapp/xslt/environment.xsl b/apps/showcase/src/main/webapp/xslt/environment.xsl index 87ae897e23..49ee1936fc 100644 --- a/apps/showcase/src/main/webapp/xslt/environment.xsl +++ b/apps/showcase/src/main/webapp/xslt/environment.xsl @@ -1,3 +1,23 @@ + diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ActionChainingTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ActionChainingTest.java index 8299be2fdf..ca8f283ad7 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ActionChainingTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ActionChainingTest.java @@ -20,11 +20,21 @@ */ package it.org.apache.struts2.showcase; -public class ActionChainingTest extends ITBaseTest { - public void test() { - beginAt("/actionchaining/actionChain1!input"); - assertTextPresent("Action Chain 1 Property 1: Property Set In Action Chain 1"); - assertTextPresent("Action Chain 2 Property 1: Property Set in Action Chain 2"); - assertTextPresent("Action Chain 3 Property 1: Property set in Action Chain 3"); +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlPage; +import org.junit.Assert; +import org.junit.Test; + +public class ActionChainingTest { + @Test + public void test() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/actionchaining/actionChain1!input"); + + final String pageAsText = page.asNormalizedText(); + Assert.assertTrue(pageAsText.contains("Action Chain 1 Property 1: Property Set In Action Chain 1")); + Assert.assertTrue(pageAsText.contains("Action Chain 2 Property 1: Property Set in Action Chain 2")); + Assert.assertTrue(pageAsText.contains("Action Chain 3 Property 1: Property set in Action Chain 3")); + } } } diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ActionTagExampleTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ActionTagExampleTest.java index 5379cfb722..668553dbd1 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ActionTagExampleTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ActionTagExampleTest.java @@ -20,10 +20,19 @@ */ package it.org.apache.struts2.showcase; -public class ActionTagExampleTest extends ITBaseTest { - public void test() { - beginAt("/tags/ui/actionTagExample!input.action"); - assertTextPresent("This text is from the called class"); - } +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlPage; +import org.junit.Assert; +import org.junit.Test; + +public class ActionTagExampleTest { + @Test + public void test() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/tags/ui/actionTagExample!input.action"); + final String pageAsText = page.asNormalizedText(); + Assert.assertTrue(pageAsText.contains("This text is from the called class")); + } + } } diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/AsyncTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/AsyncTest.java new file mode 100644 index 0000000000..8a4edd37c6 --- /dev/null +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/AsyncTest.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 it.org.apache.struts2.showcase; + +import org.htmlunit.WebClient; +import org.htmlunit.html.DomElement; +import org.htmlunit.html.HtmlForm; +import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlSubmitInput; +import org.htmlunit.html.HtmlTextInput; +import org.junit.Assert; +import org.junit.Test; + +public class AsyncTest { + @Test + public void testChatRoom() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/async/index.html"); + + final HtmlForm form = page.getForms().get(0); + + final HtmlTextInput textField = form.getInputByName("msg"); + textField.type("hello"); + + final HtmlSubmitInput button = form.getInputByValue("Send"); + final HtmlPage page2 = button.click(); + + Thread.sleep(4000); + + final DomElement msgs = page2.getElementById("msgs"); + + Assert.assertEquals("hello", msgs.asNormalizedText()); + } + } +} diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/CRUDTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/CRUDTest.java index 880f4aa1da..576e765549 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/CRUDTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/CRUDTest.java @@ -20,17 +20,33 @@ */ package it.org.apache.struts2.showcase; -public class CRUDTest extends ITBaseTest { - public void testCreate() { - beginAt("/skill/edit.action"); +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlForm; +import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlSubmitInput; +import org.htmlunit.html.HtmlTextInput; +import org.junit.Assert; +import org.junit.Test; - setTextField("currentSkill.name", "somename1"); - setTextField("currentSkill.description", "somedescription1"); +public class CRUDTest { + @Test + public void testCreate() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/skill/edit.action"); - submit(); + final HtmlForm form = page.getForms().get(0); - beginAt("/skill/list.action"); - assertTextPresent("somename1"); - assertTextPresent("somedescription1"); + final HtmlTextInput textField = form.getInputByName("currentSkill.name"); + textField.type("somename1"); + final HtmlTextInput textField2 = form.getInputByName("currentSkill.description"); + textField2.type("somedescription1"); + + final HtmlSubmitInput button = form.getInputByValue("Save"); + final HtmlPage page2 = button.click(); + final String page2Text = page2.asNormalizedText(); + + Assert.assertTrue(page2Text.contains("somename1")); + Assert.assertTrue(page2Text.contains("somedescription1")); + } } } diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ComponentTagExampleTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ComponentTagExampleTest.java index 9bf052387f..50977e0592 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ComponentTagExampleTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ComponentTagExampleTest.java @@ -20,12 +20,23 @@ */ package it.org.apache.struts2.showcase; -public class ComponentTagExampleTest extends ITBaseTest { - public void test() { - beginAt("/tags/ui/componentTagExample.jsp"); - assertTextPresent("Freemarker Custom Template - parameter 'paramName' - paramValue1"); - assertTextPresent("Freemarker Custom Template - parameter 'paramName' - paramValue4"); - assertTextPresent("JSP Custom Template - parameter 'paramName' - paramValue2"); - assertTextPresent("JSP Custom Template - parameter 'paramName' - paramValue3"); +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlPage; +import org.junit.Assert; +import org.junit.Test; + +public class ComponentTagExampleTest { + @Test + public void test() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient + .getPage(ParameterUtils.getBaseUrl() + "/tags/ui/componentTagExample.action"); + + final String pageAsText = page.asNormalizedText(); + Assert.assertTrue(pageAsText.contains("Freemarker Custom Template - parameter 'paramName' - paramValue1")); + Assert.assertTrue(pageAsText.contains("Freemarker Custom Template - parameter 'paramName' - paramValue4")); + Assert.assertTrue(pageAsText.contains("JSP Custom Template - parameter 'paramName' - paramValue2")); + Assert.assertTrue(pageAsText.contains("JSP Custom Template - parameter 'paramName' - paramValue3")); + } } } diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ConventionTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ConventionTest.java new file mode 100644 index 0000000000..6a08ea2aa2 --- /dev/null +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ConventionTest.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package it.org.apache.struts2.showcase; + +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlForm; +import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlSubmitInput; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ConventionTest { + + private WebClient webClient; + + @Before + public void setUp() throws Exception { + webClient = new WebClient(); + } + + @After + public void tearDown() throws Exception { + webClient.close(); + } + + @Test + public void listPeople() throws Exception { + HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/person/list-people.action"); + + assertThat(page.asNormalizedText()).contains( + "3\tAlexandru\tPapesco\n" + + "4\tJay\tBoss\n" + + "5\tRainer\tHermanos\n" + ); + } + + @Test + public void editPeople() throws Exception { + HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/person/edit-person.action"); + HtmlForm form = page.getForms().get(0); + + form.getInputByName("persons(1).name").setValue("Lukasz"); + form.getInputByName("persons(1).lastName").setValue("Lenart"); + form.getInputByName("persons(2).name").setValue("Kusal"); + form.getInputByName("persons(2).lastName").setValue("Kithul-Godage"); + + HtmlSubmitInput button = form.getInputByValue("Save all persons"); + page = button.click(); + + assertThat(page.asNormalizedText()).contains( + "1\tLukasz\tLenart\n" + + "2\tKusal\tKithul-Godage\n" + ); + } + + @Test + public void createPerson() throws Exception { + HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/person/new-person!input.action"); + HtmlForm form = page.getForms().get(0); + + form.getInputByName("person.name").type("Lukasz"); + form.getInputByName("person.lastName").type("Lenart"); + + HtmlSubmitInput button = form.getInputByValue("Create person"); + page = button.click(); + + assertThat(page.asNormalizedText()).contains("6\tLukasz\tLenart\n"); + } +} diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ConversionTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ConversionTest.java index b21264691b..3690be43dd 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ConversionTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ConversionTest.java @@ -20,48 +20,81 @@ */ package it.org.apache.struts2.showcase; -public class ConversionTest extends ITBaseTest { - public void testList() { - beginAt("/conversion/enterPersonsInfo.action"); - setTextField("persons[0].name", "name0"); - setTextField("persons[0].age", "0"); - setTextField("persons[1].name", "name1"); - setTextField("persons[1].age", "1"); - setTextField("persons[2].name", "name2"); - setTextField("persons[2].age", "2"); - - submit(); - - assertTextPresent("SET 0 Name: name0"); - assertTextPresent("SET 0 Age: 0"); - assertTextPresent("SET 1 Name: name1"); - assertTextPresent("SET 1 Age: 1"); - assertTextPresent("SET 2 Name: name2"); - assertTextPresent("SET 2 Age: 2"); +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlForm; +import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlSubmitInput; +import org.junit.Assert; +import org.junit.Test; + +public class ConversionTest { + @Test + public void testList() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient + .getPage(ParameterUtils.getBaseUrl() + "/conversion/enterPersonsInfo.action"); + + final HtmlForm form = page.getForms().get(0); + + form.getInputByName("persons[0].name").type("name0"); + form.getInputByName("persons[0].age").type("0"); + form.getInputByName("persons[1].name").type("name1"); + form.getInputByName("persons[1].age").type("1"); + form.getInputByName("persons[2].name").type("name2"); + form.getInputByName("persons[2].age").type("2"); + + final HtmlSubmitInput button = form.getInputByValue("Submit"); + final HtmlPage page2 = button.click(); + final String page2Text = page2.asNormalizedText(); + + Assert.assertTrue(page2Text.contains("SET 0 Name: name0")); + Assert.assertTrue(page2Text.contains("SET 0 Age: 0")); + Assert.assertTrue(page2Text.contains("SET 1 Name: name1")); + Assert.assertTrue(page2Text.contains("SET 1 Age: 1")); + Assert.assertTrue(page2Text.contains("SET 2 Name: name2")); + Assert.assertTrue(page2Text.contains("SET 2 Age: 2")); + } } - public void testSet() { - beginAt("/conversion/enterAddressesInfo.action"); - setTextField("addresses('id0').address", "address0"); - setTextField("addresses('id1').address", "address1"); - setTextField("addresses('id2').address", "address2"); + @Test + public void testSet() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient + .getPage(ParameterUtils.getBaseUrl() + "/conversion/enterAddressesInfo.action"); - submit(); + final HtmlForm form = page.getForms().get(0); - assertTextPresent("id0 -> address0"); - assertTextPresent("id1 -> address1"); - assertTextPresent("id2 -> address2"); + form.getInputByName("addresses('id0').address").type("address0"); + form.getInputByName("addresses('id1').address").type("address1"); + form.getInputByName("addresses('id2').address").type("address2"); + + final HtmlSubmitInput button = form.getInputByValue("Submit"); + final HtmlPage page2 = button.click(); + final String page2Text = page2.asNormalizedText(); + + Assert.assertTrue(page2Text.contains("id0 -> address0")); + Assert.assertTrue(page2Text.contains("id1 -> address1")); + Assert.assertTrue(page2Text.contains("id2 -> address2")); + } } - public void testEnum() { - beginAt("/conversion/enterOperationEnumInfo.action"); - checkCheckbox("selectedOperations", "ADD"); - checkCheckbox("selectedOperations", "MINUS"); + @Test + public void testEnum() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient + .getPage(ParameterUtils.getBaseUrl() + "/conversion/enterOperationEnumInfo.action"); + + final HtmlForm form = page.getForms().get(0); - submit(); + form.getInputByValue("ADD").setChecked(true); + form.getInputByValue("MINUS").setChecked(true); - assertTextPresent("ADD"); - assertTextPresent("MINUS"); + final HtmlSubmitInput button = form.getInputByValue("Submit"); + final HtmlPage page2 = button.click(); + final String page2Text = page2.asNormalizedText(); + + Assert.assertTrue(page2Text.contains("ADD")); + Assert.assertTrue(page2Text.contains("MINUS")); + } } } - diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/DispatcherResultTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/DispatcherResultTest.java new file mode 100644 index 0000000000..04fd47d353 --- /dev/null +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/DispatcherResultTest.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 it.org.apache.struts2.showcase; + +import org.htmlunit.WebClient; +import org.htmlunit.html.DomElement; +import org.htmlunit.html.HtmlPage; +import org.junit.Assert; +import org.junit.Test; + +public class DispatcherResultTest { + + @Test + public void testDispatchingToJSP() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/dispatcher/dispatch.action"); + + DomElement div = page.getElementById("dispatcher-result"); + Assert.assertEquals("This page is a result of \"dispatching\" to it from an action", div.asNormalizedText()); + } + } + + @Test + public void testDispatchingToAction() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/dispatcher/forward.action"); + + DomElement div = page.getElementById("dispatcher-result"); + Assert.assertEquals("This page is a result of \"dispatching\" to it from an action", div.asNormalizedText()); + } + } + +} diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ExecAndWaitTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ExecAndWaitTest.java index fce922bf9c..ab5314cbed 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ExecAndWaitTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ExecAndWaitTest.java @@ -20,16 +20,34 @@ */ package it.org.apache.struts2.showcase; -public class ExecAndWaitTest extends ITBaseTest { - public void testNodelay() throws InterruptedException { - beginAt("/wait/example1.jsp"); +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlForm; +import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlSubmitInput; +import org.htmlunit.html.HtmlTextInput; +import org.junit.Assert; +import org.junit.Test; - setTextField("time", "7000"); - submit(); - assertTextPresent("We are processing your request. Please wait."); +public class ExecAndWaitTest { + @Test + public void testNodelay() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/wait/example1.action"); - //hit it again - beginAt("/wait/longProcess1.action?time=1000"); - assertTextPresent("We are processing your request. Please wait."); + final HtmlForm form = page.getForms().get(0); + + final HtmlTextInput textField = form.getInputByName("time"); + textField.type("7000"); + + final HtmlSubmitInput button = form.getInputByValue("submit"); + final HtmlPage page2 = button.click(); + + Assert.assertTrue(page2.asNormalizedText().contains("We are processing your request. Please wait.")); + + // hit it again + final HtmlPage page3 = webClient + .getPage(ParameterUtils.getBaseUrl() + "/wait/longProcess1.action?time=1000"); + Assert.assertTrue(page3.asNormalizedText().contains("We are processing your request. Please wait.")); + } } } diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FileDownloadTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FileDownloadTest.java index 1e7aa4150d..7bf488403f 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FileDownloadTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FileDownloadTest.java @@ -20,21 +20,50 @@ */ package it.org.apache.struts2.showcase; +import java.io.IOException; +import java.io.InputStream; import java.net.URL; -import java.net.MalformedURLException; -public class FileDownloadTest extends ITBaseTest { - public void testImage() throws InterruptedException, MalformedURLException { - beginAt("/filedownload/download.action"); +import org.htmlunit.Page; +import org.htmlunit.WebClient; +import org.junit.Assert; +import org.junit.Test; - URL url = new URL("http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/showcase/src/main/webapp/images/struts.gif"); - assertDownloadedFileEquals(url); +public class FileDownloadTest { + @Test + public void testImage() throws Exception { + try (final WebClient webClient = new WebClient()) { + final Page page = webClient.getPage(ParameterUtils.getBaseUrl() + "/filedownload/download.action"); + + URL url = new URL( + "https://gitbox.apache.org/repos/asf?p=struts.git;a=blob_plain;f=apps/showcase/src/main/webapp/images/struts.gif;hb=HEAD"); + + Assert.assertTrue(areFilesEqual(url.openStream(), page.getWebResponse().getContentAsStream())); + } } - public void testZip() throws InterruptedException, MalformedURLException { - beginAt("/filedownload/download2.action"); + @Test + public void testZip() throws Exception { + try (final WebClient webClient = new WebClient()) { + final Page page = webClient.getPage(ParameterUtils.getBaseUrl() + "/filedownload/download2.action"); + + URL url = new URL( + "https://gitbox.apache.org/repos/asf?p=struts.git;a=blob_plain;f=apps/showcase/src/main/webapp/images/struts-gif.zip;hb=HEAD"); + + Assert.assertTrue(areFilesEqual(url.openStream(), page.getWebResponse().getContentAsStream())); + } + } - URL url = new URL("http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/showcase/src/main/webapp/images/struts-gif.zip"); - assertDownloadedFileEquals(url); + private boolean areFilesEqual(InputStream i1, InputStream i2) throws IOException { + // read and compare bytes pair-wise + int b1, b2; + do { + b1 = i1.read(); + b2 = i2.read(); + } while (b1 == b2 && b1 != -1 && b2 != -1); + i1.close(); + i2.close(); + // true only if end of file is reached for both + return (b1 == -1) && (b2 == -1); } } diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FileUploadTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FileUploadTest.java new file mode 100644 index 0000000000..c0baaf3a8d --- /dev/null +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FileUploadTest.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 it.org.apache.struts2.showcase; + +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlFileInput; +import org.htmlunit.html.HtmlForm; +import org.htmlunit.html.HtmlInput; +import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlSubmitInput; +import org.junit.Test; + +import java.io.File; +import java.io.FileWriter; +import java.security.SecureRandom; + +import static org.assertj.core.api.Assertions.assertThat; + +public class FileUploadTest { + + @Test + public void testSimpleFileUpload() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/fileupload/doUpload.action"); + final HtmlForm form = page.getFormByName("doUpload"); + HtmlInput captionInput = form.getInputByName("caption"); + HtmlFileInput uploadInput = form.getInputByName("upload"); + captionInput.type("some caption"); + File tempFile = File.createTempFile("testEmptyFile", ".txt"); + tempFile.deleteOnExit(); + + try (FileWriter writer = new FileWriter(tempFile)) { + writer.append("Some strings"); + writer.flush(); + } + + uploadInput.setValue(tempFile.getAbsolutePath()); + final HtmlSubmitInput button = form.getInputByValue("Submit"); + final HtmlPage resultPage = button.click(); + + String content = resultPage.getVisibleText(); + assertThat(content).contains( + "ContentType: text/plain", + "Original FileName: " + tempFile.getName(), + "Caption: some caption", + "Size: 12", + "Input name: upload" + ); + } + } + + @Test + public void testUploadOverMaxSize() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/fileupload/doUpload.action"); + final HtmlForm form = page.getFormByName("doUpload"); + HtmlInput captionInput = form.getInputByName("caption"); + HtmlFileInput uploadInput = form.getInputByName("upload"); + + captionInput.type("Large file"); + + File tempFile = File.createTempFile("testEmptyFile", ".txt"); + SecureRandom rng = new SecureRandom(); + tempFile.deleteOnExit(); + try (FileWriter writer = new FileWriter(tempFile)) { + for (int i = 0; i < 10240; ++i) { + String line = String.format("%s %s%n", rng.nextInt(), rng.nextInt()); + writer.append(line); + } + writer.flush(); + } + + uploadInput.setValue(tempFile.getAbsolutePath()); + final HtmlSubmitInput button = form.getInputByValue("Submit"); + final HtmlPage resultPage = button.click(); + + String content = resultPage.getVisibleText(); + System.out.println(content); + assertThat(content).contains( + "Request exceeded allowed size limit! Max size allowed is: 10,240!" + ); + } + } + +} diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ForwardTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ForwardTest.java new file mode 100644 index 0000000000..5eeb2b536e --- /dev/null +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ForwardTest.java @@ -0,0 +1,41 @@ +/* + * $Id$ + * + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package it.org.apache.struts2.showcase; + +import org.htmlunit.WebClient; +import org.htmlunit.html.DomElement; +import org.htmlunit.html.HtmlPage; +import org.junit.Assert; +import org.junit.Test; + +public class ForwardTest { + + @Test + public void testServletForwardingToAction() throws Exception { + try (final WebClient webClient = new WebClient()) { + // Struts excluded URL, as defined by struts.action.excludePattern + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/testServlet/forward"); + + DomElement div = page.getElementById("dispatcher-result"); + Assert.assertEquals("This page is a result of \"dispatching\" to it from an action", div.asNormalizedText()); + } + } +} diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FreeMarkerManagerTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FreeMarkerManagerTest.java index e0006a641d..b6478ef066 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FreeMarkerManagerTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/FreeMarkerManagerTest.java @@ -20,25 +20,39 @@ */ package it.org.apache.struts2.showcase; -import java.net.MalformedURLException; -import java.net.URL; +import org.htmlunit.WebClient; +import org.htmlunit.html.DomElement; +import org.htmlunit.html.HtmlPage; +import org.junit.Assert; +import org.junit.Test; -public class FreeMarkerManagerTest extends ITBaseTest { - public void testCustomManager() { - beginAt("/freemarker/customFreemarkerManagerDemo.action"); +public class FreeMarkerManagerTest { + @Test + public void testCustomManager() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient + .getPage(ParameterUtils.getBaseUrl() + "/freemarker/customFreemarkerManagerDemo.action"); - String date = getElementTextByXPath("//*[@id='todaysDate']"); - assertNotNull(date); - assertTrue(date.length() > 0); + final DomElement date = page.getElementById("todaysDate"); + Assert.assertNotNull(date); + Assert.assertFalse(date.asNormalizedText().isEmpty()); - String time = getElementTextByXPath("//*[@id='timeNow']"); - assertNotNull(time); - assertTrue(time.length() > 0); + final DomElement time = page.getElementById("timeNow"); + Assert.assertNotNull(time); + Assert.assertFalse(time.asNormalizedText().isEmpty()); + } } - public void testTags() { - beginAt("/freemarker/standardTags.action"); - assertElementPresent("test_name"); - assertElementPresent("test_"); + @Test + public void testTags() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/freemarker/standardTags.action"); + + final DomElement date = page.getElementById("test_name"); + Assert.assertNotNull(date); + + final DomElement time = page.getElementById("test"); + Assert.assertNotNull(time); + } } } diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ITBaseTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ITBaseTest.java deleted file mode 100644 index 0aa35f1fef..0000000000 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ITBaseTest.java +++ /dev/null @@ -1,30 +0,0 @@ -/* - * $Id$ - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package it.org.apache.struts2.showcase; - -import net.sourceforge.jwebunit.junit.WebTestCase; - -public abstract class ITBaseTest extends WebTestCase { - - public void setUp() throws Exception { - getTestContext().setBaseUrl(ParameterUtils.getBaseUrl()); - } -} diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ModelDrivenTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ModelDrivenTest.java new file mode 100644 index 0000000000..b3656fc7ca --- /dev/null +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ModelDrivenTest.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 it.org.apache.struts2.showcase; + +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlForm; +import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlSubmitInput; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ModelDrivenTest { + + private WebClient webClient; + + @Before + public void setUp() throws Exception { + webClient = new WebClient(); + } + + @After + public void tearDown() throws Exception { + webClient.close(); + } + + @Test + public void submit() throws Exception { + HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/modelDriven/modelDriven.action"); + HtmlForm form = page.getForms().get(0); + + form.getInputByName("name").setValue("Johannes"); + form.getInputByName("age").setValue("21"); + form.getInputByName("bustedBefore").setChecked(true); + form.getTextAreaByName("description").setText("Deals bugs"); + + HtmlSubmitInput button = form.getInputByValue("Submit"); + page = button.click(); + + assertThat(page.getElementById("name").asNormalizedText()).isEqualTo("Johannes"); + assertThat(page.getElementById("age").asNormalizedText()).isEqualTo("21"); + assertThat(page.getElementById("bustedBefore").asNormalizedText()).isEqualTo("true"); + assertThat(page.getElementById("description").asNormalizedText()).isEqualTo("Deals bugs"); + } +} diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StaticContentTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StaticContentTest.java new file mode 100644 index 0000000000..f329e78f3f --- /dev/null +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StaticContentTest.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 it.org.apache.struts2.showcase; + +import org.htmlunit.FailingHttpStatusCodeException; +import org.htmlunit.WebClient; +import org.junit.Assert; +import org.junit.Test; + +public class StaticContentTest { + + @Test + public void testInvalidResources1() throws Exception { + try (final WebClient webClient = new WebClient()) { + try { + webClient.getPage(ParameterUtils.getBaseUrl() + "/struts.."); + Assert.fail("Previous request should have failed"); + } catch (FailingHttpStatusCodeException e) { + Assert.assertEquals("Not Found", e.getStatusMessage()); + Assert.assertEquals(404, e.getStatusCode()); + } + } + } + + @Test + public void testInvalidResources2() throws Exception { + try (final WebClient webClient = new WebClient()) { + try { + webClient.getPage(ParameterUtils.getBaseUrl() + "/static/..%252f"); + Assert.fail("Previous request should have failed"); + } catch (FailingHttpStatusCodeException e) { + Assert.assertEquals("Not Found", e.getStatusMessage()); + Assert.assertEquals(404, e.getStatusCode()); + } + } + } + +} diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StrutsParametersTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StrutsParametersTest.java new file mode 100644 index 0000000000..7b4d082697 --- /dev/null +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/StrutsParametersTest.java @@ -0,0 +1,240 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package it.org.apache.struts2.showcase; + +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlPage; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.springframework.web.util.UriComponentsBuilder; + +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +import static org.junit.Assert.assertEquals; + +public class StrutsParametersTest { + + private WebClient webClient; + + @Before + public void setUp() throws Exception { + webClient = new WebClient(); + } + + @After + public void tearDown() throws Exception { + webClient.close(); + } + + @Test + public void public_StringField_WithoutGetterSetter_FieldNotAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicField", "yes"); + params.put("varToPrint", "publicField"); + assertText(params, "publicField{no}"); + } + + @Test + public void public_StringField_WithoutGetterSetter_FieldAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicFieldAnnotated", "yes"); + params.put("varToPrint", "publicFieldAnnotated"); + assertText(params, "publicFieldAnnotated{yes}"); + } + + @Test + public void private_StringField_WithSetter_MethodNotAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("privateFieldMethod", "yes"); + params.put("varToPrint", "privateField"); + assertText(params, "privateField{no}"); + } + + @Test + public void private_StringField_WithSetter_MethodAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("privateFieldMethodAnnotated", "yes"); + params.put("varToPrint", "privateField"); + assertText(params, "privateField{yes}"); + } + + @Test + public void public_ArrayField_WithoutGetterSetter_FieldNotAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicArray[0]", "1"); + params.put("varToPrint", "publicArray"); + assertText(params, "publicArray{[0]}"); + } + + @Test + public void public_ArrayField_WithoutGetterSetter_FieldAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicArrayAnnotated[0]", "1"); + params.put("varToPrint", "publicArrayAnnotated"); + assertText(params, "publicArrayAnnotated{[1]}"); + } + + @Test + public void public_ListField_WithoutGetterSetter_FieldNotAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicList[0]", "yes"); + params.put("varToPrint", "publicList"); + assertText(params, "publicList{[no]}"); + } + + @Test + public void public_ListField_WithoutGetterSetter_FieldAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicListAnnotated[0]", "yes"); + params.put("varToPrint", "publicListAnnotated"); + assertText(params, "publicListAnnotated{[yes]}"); + } + + @Test + public void private_ListField_WithGetterNoSetter_MethodNotAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("privateListMethod[0]", "yes"); + params.put("varToPrint", "privateList"); + assertText(params, "privateList{[no]}"); + } + + @Test + public void private_ListField_WithGetterNoSetter_MethodAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("privateListMethodAnnotated[0]", "yes"); + params.put("varToPrint", "privateList"); + assertText(params, "privateList{[yes]}"); + } + + @Test + public void public_MapField_WithoutGetterSetter_FieldNotAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicMap['key']", "yes"); + params.put("varToPrint", "publicMap"); + assertText(params, "publicMap{{key=no}}"); + } + + @Test + public void public_MapField_WithoutGetterSetter_FieldAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicMapAnnotated['key']", "yes"); + params.put("varToPrint", "publicMapAnnotated"); + assertText(params, "publicMapAnnotated{{key=yes}}"); + } + + @Test + public void public_MapField_Insert_WithoutGetterSetter_FieldNotAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicMap[999]", "yes"); + params.put("varToPrint", "publicMap"); + assertText(params, "publicMap{{key=no}}"); + } + + @Test + public void public_MapField_Insert_WithoutGetterSetter_FieldAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicMapAnnotated[999]", "yes"); + params.put("varToPrint", "publicMapAnnotated"); + assertText(params, "publicMapAnnotated{{999=yes, key=no}}"); + } + + @Test + public void public_MyDtoField_WithoutGetter_FieldNotAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicMyDto.str", "yes"); + params.put("publicMyDto.map['key']", "yes"); + params.put("publicMyDto.array[0]", "1"); + params.put("varToPrint", "publicMyDto"); + assertText(params, "publicMyDto{str=no, map={key=no}, array=[0]}"); + } + + @Test + public void public_MyDtoField_WithoutGetter_FieldAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("publicMyDtoAnnotated.str", "yes"); + params.put("publicMyDtoAnnotated.map['key']", "yes"); + params.put("publicMyDtoAnnotated.array[0]", "1"); + params.put("varToPrint", "publicMyDtoAnnotated"); + assertText(params, "publicMyDtoAnnotated{str=yes, map={key=yes}, array=[1]}"); + } + + @Test + public void public_MyDtoField_WithoutGetter_FieldAnnotatedDepthOne() throws Exception { + Map params = new HashMap<>(); + params.put("publicMyDtoAnnotatedDepthOne.str", "yes"); + params.put("publicMyDtoAnnotatedDepthOne.map['key']", "yes"); + params.put("publicMyDtoAnnotatedDepthOne.array[0]", "1"); + params.put("varToPrint", "publicMyDtoAnnotatedDepthOne"); + assertText(params, "publicMyDtoAnnotatedDepthOne{str=yes, map={key=no}, array=[0]}"); + } + + @Test + public void private_MyDtoField_WithGetter_MethodNotAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("unsafeMethodMyDto.str", "yes"); + params.put("unsafeMethodMyDto.map['key']", "yes"); + params.put("unsafeMethodMyDto.array[0]", "1"); + params.put("varToPrint", "privateMyDto"); + assertText(params, "privateMyDto{str=no, map={key=no}, array=[0]}"); + } + + @Test + public void private_MyDtoField_WithGetter_MethodNotAnnotated_Alternate() throws Exception { + Map params = new HashMap<>(); + params.put("unsafeMethodMyDto['str']", "yes"); + params.put("unsafeMethodMyDto['map']['key']", "yes"); + params.put("unsafeMethodMyDto['map'][999]", "yes"); + params.put("unsafeMethodMyDto['array'][0]", "1"); + params.put("varToPrint", "privateMyDto"); + assertText(params, "privateMyDto{str=no, map={key=no}, array=[0]}"); + } + + @Test + public void private_MyDtoField_WithGetter_MethodAnnotated() throws Exception { + Map params = new HashMap<>(); + params.put("safeMethodMyDto.str", "yes"); + params.put("safeMethodMyDto.map['key']", "yes"); + params.put("safeMethodMyDto.array[0]", "1"); + params.put("varToPrint", "privateMyDto"); + assertText(params, "privateMyDto{str=yes, map={key=yes}, array=[1]}"); + } + + @Test + public void private_MyDtoField_WithGetter_MethodAnnotatedDepthOne() throws Exception { + Map params = new HashMap<>(); + params.put("safeMethodMyDtoDepthOne.str", "yes"); + params.put("safeMethodMyDtoDepthOne.map['key']", "yes"); + params.put("safeMethodMyDtoDepthOne.array[0]", "1"); + params.put("varToPrint", "privateMyDto"); + assertText(params, "privateMyDto{str=yes, map={key=no}, array=[0]}"); + } + + private void assertText(Map params, String text) throws IOException { + UriComponentsBuilder builder = UriComponentsBuilder.fromUriString(ParameterUtils.getBaseUrl()) + .path("/paramsannotation/test.action"); + params.forEach(builder::queryParam); + String url = builder.toUriString(); + HtmlPage page = webClient.getPage(url); + String output = page.getElementById("output").asNormalizedText(); + assertEquals(text, output); + } +} diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/UITagExampleTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/UITagExampleTest.java index 0f50e81735..bd822839f2 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/UITagExampleTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/UITagExampleTest.java @@ -20,36 +20,55 @@ */ package it.org.apache.struts2.showcase; -public class UITagExampleTest extends ITBaseTest { - public void testInputForm() { - setScriptingEnabled(false); - beginAt("/tags/ui/example!input.action"); - assertFormPresent("exampleSubmit"); - // text box - assertFormElementPresent("name"); - // textarea - assertFormElementPresent("bio"); - // select - assertFormElementPresent("favouriteColor"); - // checkbox list - assertFormElementPresent("friends"); - // checkbox - assertFormElementPresent("legalAge"); - - // set fields - setTextField("name", "name"); - setTextField("bio", "bio"); - selectOption("favouriteColor", "Red"); - checkCheckbox("friends", "Patrick"); - checkCheckbox("friends", "Jason"); - checkCheckbox("legalAge"); - - submit(); - - assertTextInElement("name", "name"); - assertTextInElement("bio", "bio"); - assertTextInElement("favouriteColor", "Red"); - assertTextInElement("friends", "[Patrick, Jason]"); - assertTextInElement("legalAge", "true"); +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlCheckBoxInput; +import org.htmlunit.html.HtmlForm; +import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlSelect; +import org.htmlunit.html.HtmlSubmitInput; +import org.htmlunit.html.HtmlTextArea; +import org.htmlunit.html.HtmlTextInput; +import org.junit.Assert; +import org.junit.Test; + +public class UITagExampleTest { + @Test + public void testInputForm() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/tags/ui/example!input.action"); + + final HtmlForm form = page.getFormByName("exampleSubmit"); + Assert.assertNotNull(form); + + final HtmlTextInput textField = form.getInputByName("name"); + final HtmlTextArea textField2 = form.getTextAreaByName("bio"); + final HtmlSelect textField3 = form.getSelectByName("favouriteColor"); + final HtmlCheckBoxInput textField4 = form.getInputByValue("Patrick"); + final HtmlCheckBoxInput textField41 = form.getInputByValue("Jason"); + final HtmlCheckBoxInput textField5 = form.getInputByName("legalAge"); + + Assert.assertNotNull(textField); + Assert.assertNotNull(textField2); + Assert.assertNotNull(textField3); + Assert.assertNotNull(textField4); + Assert.assertNotNull(textField41); + Assert.assertNotNull(textField5); + + textField.type("name"); + textField2.type("bio"); + textField3.setSelectedAttribute("Red", true); + textField4.setChecked(true); + textField41.setChecked(true); + textField5.setChecked(true); + + final HtmlSubmitInput button = form.getInputByValue("Submit"); + final HtmlPage page2 = button.click(); + + Assert.assertEquals("name", page2.getElementById("name").asNormalizedText()); + Assert.assertEquals("bio", page2.getElementById("bio").asNormalizedText()); + Assert.assertEquals("Red", page2.getElementById("favouriteColor").asNormalizedText()); + Assert.assertEquals("[Patrick, Jason]", page2.getElementById("friends").asNormalizedText()); + Assert.assertEquals("true", page2.getElementById("legalAge").asNormalizedText()); + } } } diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ValidationTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ValidationTest.java index 86a3fb27f0..223256e429 100644 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ValidationTest.java +++ b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/ValidationTest.java @@ -20,27 +20,43 @@ */ package it.org.apache.struts2.showcase; -public class ValidationTest extends ITBaseTest { - public void testFieldValidators() { - beginAt("/validation/showFieldValidatorsExamples.action"); +import org.htmlunit.WebClient; +import org.htmlunit.html.HtmlForm; +import org.htmlunit.html.HtmlPage; +import org.htmlunit.html.HtmlSubmitInput; +import org.junit.Assert; +import org.junit.Test; - setTextField("integerValidatorField", "nonint"); - setTextField("dateValidatorField", "nondate"); - setTextField("emailValidatorField", "!@@#%"); - setTextField("urlValidatorField", "!@@#%"); - setTextField("stringLengthValidatorField", "a"); - setTextField("regexValidatorField", "abc"); - setTextField("fieldExpressionValidatorField", "abc"); +public class ValidationTest { + @Test + public void testFieldValidators() throws Exception { + try (final WebClient webClient = new WebClient()) { + final HtmlPage page = webClient + .getPage(ParameterUtils.getBaseUrl() + "/validation/showFieldValidatorsExamples.action"); - submit(); + final HtmlForm form = page.getForms().get(0); - assertTextPresent("Invalid field value for field \"dateValidatorField\""); - assertTextPresent("Invalid field value for field \"integerValidatorField\""); - assertTextPresent("required and must be string"); - assertTextPresent("must be a valid email if supplied"); - assertTextPresent("must be a valid url if supplied "); - assertTextPresent("must be a String of a specific greater than 1 less than 5 if specified "); - assertTextPresent("regexValidatorField must match a regexp (.*\\.txt) if specified "); - assertTextPresent("must be the same as the Required Validator Field if specified "); + form.getInputByName("integerValidatorField").type("nonint"); + form.getInputByName("dateValidatorField").type("nondate"); + form.getInputByName("emailValidatorField").type("!@@#%"); + form.getInputByName("urlValidatorField").type("!@@#%"); + form.getInputByName("stringLengthValidatorField").type("a"); + form.getInputByName("regexValidatorField").type("abc"); + form.getInputByName("fieldExpressionValidatorField").type("abc"); + + final HtmlSubmitInput button = form.getInputByValue("Submit"); + final HtmlPage page2 = button.click(); + final String page2Text = page2.asNormalizedText(); + + Assert.assertTrue(page2Text.contains("Invalid field value for field \"dateValidatorField\"")); + Assert.assertTrue(page2Text.contains("Invalid field value for field \"integerValidatorField\"")); + Assert.assertTrue(page2Text.contains("required and must be string")); + Assert.assertTrue(page2Text.contains("must be a valid email if supplied")); + Assert.assertTrue(page2Text.contains("must be a valid url if supplied")); + Assert.assertTrue( + page2Text.contains("must be a String of a specific greater than 1 less than 5 if specified")); + Assert.assertTrue(page2Text.contains("regexValidatorField must match a regexp (.*\\.txt) if specified")); + Assert.assertTrue(page2Text.contains("must be the same as the Required Validator Field if specified")); + } } } diff --git a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/staticcontent/StaticContentTest.java b/apps/showcase/src/test/java/it/org/apache/struts2/showcase/staticcontent/StaticContentTest.java deleted file mode 100644 index a6393b87b0..0000000000 --- a/apps/showcase/src/test/java/it/org/apache/struts2/showcase/staticcontent/StaticContentTest.java +++ /dev/null @@ -1,37 +0,0 @@ -package it.org.apache.struts2.showcase.staticcontent; - -import it.org.apache.struts2.showcase.ITBaseTest; - -import java.io.IOException; - -import net.sourceforge.jwebunit.exception.TestingEngineResponseException; - -public class StaticContentTest extends ITBaseTest { - - public void testInvalidRersources1() throws IOException { - try { - beginAt("/struts.."); - fail("Previous request should have failed"); - } catch (TestingEngineResponseException ex) { - // ok - } - } - - public void testInvalidRersources2() throws IOException { - try { - beginAt("/struts/..%252f"); - fail("Previous request should have failed"); - } catch (TestingEngineResponseException ex) { - // ok - } - } - - /*public void testInvalidRersources3() throws IOException { - try { - beginAt("/struts/..%252f..%252f..%252fWEB-INF/classes/org/apache/struts2/showcase/action/EmployeeAction.class/"); - fail("Previous request should have failed"); - } catch (TestingEngineResponseException ex) { - // ok - } - }*/ -} diff --git a/apps/showcase/src/test/java/org/apache/struts2/showcase/filedownload/FileDownloadActionTest.java b/apps/showcase/src/test/java/org/apache/struts2/showcase/filedownload/FileDownloadActionTest.java index cf8fbe3bcb..03ff90a23d 100644 --- a/apps/showcase/src/test/java/org/apache/struts2/showcase/filedownload/FileDownloadActionTest.java +++ b/apps/showcase/src/test/java/org/apache/struts2/showcase/filedownload/FileDownloadActionTest.java @@ -1,3 +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. + */ package org.apache.struts2.showcase.filedownload; import org.junit.Before; diff --git a/assembly/README.md b/assembly/README.md new file mode 100644 index 0000000000..2bcd93d080 --- /dev/null +++ b/assembly/README.md @@ -0,0 +1,3 @@ +# Struts 2 Assemblies +This module is used to prepare ZIP archives with different set of JARs, like code source, Javadocs, etc. +It's a part of the release process, it shouldn't be used directly by users. diff --git a/assembly/pom.xml b/assembly/pom.xml index 6bd64b71eb..b59fbed0ec 100644 --- a/assembly/pom.xml +++ b/assembly/pom.xml @@ -1,31 +1,49 @@ + + 4.0.0 org.apache.struts struts2-parent - 2.5.11-SNAPSHOT + 7.0.4-SNAPSHOT + ../parent/pom.xml struts2-assembly pom Struts 2 Assembly - - + + UTF-8 - - maven-site-plugin - - true - true - false - - + true + true + + + - org.codehaus.mojo - dependency-maven-plugin - 1.0 + org.apache.maven.plugins + maven-dependency-plugin copy-war @@ -58,50 +76,49 @@ maven-antrun-plugin - cwiki-docs + docs prepare-package run - - + + - + - - + - + + - - - - - + + org.apache.maven.plugins maven-assembly-plugin + 3.7.1 make-assembly package - attached + single + false src/main/assembly/all.xml src/main/assembly/lib.xml @@ -111,8 +128,8 @@ src/main/assembly/docs.xml struts-${project.version} - target/assembly/out - target/assembly/work + ${project.build.directory}/assembly/out + ${project.build.directory}/assembly/work @@ -152,12 +169,12 @@ org.apache.struts - struts2-dwr-plugin + struts2-jasperreports-plugin org.apache.struts - struts2-jasperreports-plugin + struts2-jasperreports7-plugin @@ -170,39 +187,16 @@ struts2-junit-plugin - - org.apache.struts - struts2-pell-multipart-plugin - - - - org.apache.struts - struts2-plexus-plugin - - - - org.apache.struts - struts2-portlet-plugin - - org.apache.struts struts2-rest-plugin - - org.apache.struts - struts2-sitegraph-plugin - - - - org.apache.struts - struts2-sitemesh-plugin - org.apache.struts struts2-spring-plugin + org.apache.struts struts2-testng-plugin @@ -213,44 +207,9 @@ struts2-tiles-plugin - - org.apache.struts - struts2-oval-plugin - - org.apache.struts struts2-json-plugin - - - org.apache.struts - struts2-embeddedjsp-plugin - - - - org.apache.struts - struts2-gxp-plugin - - - - org.apache.struts - struts2-osgi-plugin - - - - org.apache.struts - struts2-osgi-admin-bundle - - - - org.apache.struts - struts2-osgi-demo-bundle - - - - - UTF-8 - diff --git a/assembly/src/main/assembly/all.xml b/assembly/src/main/assembly/all.xml index 6d8fefb69a..4bb1d142b1 100644 --- a/assembly/src/main/assembly/all.xml +++ b/assembly/src/main/assembly/all.xml @@ -1,7 +1,6 @@ + - - all - - zip - - - - false - lib - runtime - - junit:junit - org.testng:testng - - - - - - src/main/resources - - - README* - LICENSE* - NOTICE* - - - - ../core/src/main/resources - - - FREEMARKER-LICENSE.txt - OGNL-LICENSE.txt - - - - ../plugins/plexus/src/main/resources - - - CLASSWORLDS-LICENSE.txt - - - - ../plugins/rest/src/main/resources - - - XSTREAM-LICENSE.txt - XPP3-LICENSE.txt - - - - ../plugins/sitemesh/src/main/resources - - - SITEMESH-LICENSE.txt - - - - ../plugins/oval/src/main/resources - - - OVAL-LICENSE.txt - XSTREAM-LICENSE.txt - - - - target/apps - apps - - *.war - - - - - - ../core/target/site - docs/struts2-core - - - ../core/target/apidocs - docs/struts2-core-apidocs - + all + + zip + + + + false + lib + runtime + + junit:junit + org.testng:testng + + + + + + src/main/resources + + + README* + LICENSE* + NOTICE* + + + + ../core/src/main/resources + + + FREEMARKER-LICENSE.txt + OGNL-LICENSE.txt + + + + ../plugins/rest/src/main/resources + + + XSTREAM-LICENSE.txt + XPP3-LICENSE.txt + + + + target/apps + apps + + *.war + + - - - target/cwiki - docs/docs - + + + ../core/target/site + docs/struts2-core + + + ../core/target/apidocs + docs/struts2-core-apidocs + - - - - ../plugins/bean-validation/target/apidocs - docs/struts2-plugins/struts2-bean-validation/apidocs - - - ../plugins/cdi/target/apidocs - docs/struts2-plugins/struts2-cdi-plugin/apidocs - - - ../plugins/config-browser/target/apidocs - docs/struts2-plugins/struts2-config-browser-plugin/apidocs - - - ../plugins/convention/target/apidocs - docs/struts2-plugins/struts2-convention-plugin/apidocs - - - ../plugins/dwr/target/apidocs - docs/struts2-plugins/struts2-dwr-plugin/apidocs - - - ../plugins/embeddedjsp/target/apidocs - docs/struts2-plugins/struts2-embeddedjsp-plugin/apidocs - - - ../plugins/gxp/target/apidocs - docs/struts2-plugins/struts2-gxp-plugin/apidocs - - - ../plugins/jasperreports/target/apidocs - docs/struts2-plugins/struts2-jasperreports-plugin/apidocs - - - ../plugins/javatemplates/target/apidocs - docs/struts2-plugins/struts2-javatemplates-plugin/apidocs - - - ../plugins/jfreechart/target/apidocs - docs/struts2-plugins/struts2-jfreechart-plugin/apidocs - - - ../plugins/json/target/apidocs - docs/struts2-plugins/struts2-json-plugin/apidocs - - - ../plugins/junit/target/apidocs - docs/struts2-plugins/struts2-junit-plugin/apidocs - - - ../plugins/osgi/target/apidocs - docs/struts2-plugins/struts2-osgi-plugin/apidocs - - - ../plugins/oval/target/apidocs - docs/struts2-plugins/struts2-oval-plugin/apidocs - - - ../plugins/pell-multipart/target/apidocs - docs/struts2-plugins/struts2-pell-multipart-plugin/apidocs - - - ../plugins/plexus/target/apidocs - docs/struts2-plugins/struts2-plexus-plugin/apidocs - - - ../plugins/portlet/target/apidocs - docs/struts2-plugins/struts2-portlet-plugin/apidocs - - - ../plugins/portlet-tiles/target/apidocs - docs/struts2-plugins/struts2-portlet-tiles-plugin/apidocs - - - ../plugins/rest/target/apidocs - docs/struts2-plugins/struts2-rest-plugin/apidocs - - - ../plugins/sitegraph/target/apidocs - docs/struts2-plugins/struts2-sitegraph-plugin/apidocs - - - ../plugins/sitemesh/target/apidocs - docs/struts2-plugins/struts2-sitemesh-plugin/apidocs - - - ../plugins/spring/target/apidocs - docs/struts2-plugins/struts2-spring-plugin/apidocs - - - ../plugins/testng/target/apidocs - docs/struts2-plugins/struts2-testng-plugin/apidocs - - - ../plugins/tiles/target/apidocs - docs/struts2-plugins/struts2-tiles-plugin/apidocs - + + + target/docs + docs/docs + - - - ../bundles/admin/target/site - docs/struts2-bundles/admin - - - - ../bundles/demo/target/site - docs/struts2-bundles/demo - + + + + ../plugins/async/target/apidocs + docs/struts2-plugins/struts2-async-validation/apidocs + + + ../plugins/bean-validation/target/apidocs + docs/struts2-plugins/struts2-bean-validation/apidocs + + + ../plugins/cdi/target/apidocs + docs/struts2-plugins/struts2-cdi-plugin/apidocs + + + ../plugins/config-browser/target/apidocs + docs/struts2-plugins/struts2-config-browser-plugin/apidocs + + + ../plugins/convention/target/apidocs + docs/struts2-plugins/struts2-convention-plugin/apidocs + + + ../plugins/jasperreports/target/apidocs + docs/struts2-plugins/struts2-jasperreports-plugin/apidocs + + + ../plugins/javatemplates/target/apidocs + docs/struts2-plugins/struts2-javatemplates-plugin/apidocs + + + ../plugins/jfreechart/target/apidocs + docs/struts2-plugins/struts2-jfreechart-plugin/apidocs + + + ../plugins/json/target/apidocs + docs/struts2-plugins/struts2-json-plugin/apidocs + + + ../plugins/junit/target/apidocs + docs/struts2-plugins/struts2-junit-plugin/apidocs + + + ../plugins/rest/target/apidocs + docs/struts2-plugins/struts2-rest-plugin/apidocs + + + ../plugins/spring/target/apidocs + docs/struts2-plugins/struts2-spring-plugin/apidocs + + + ../plugins/testng/target/apidocs + docs/struts2-plugins/struts2-testng-plugin/apidocs + + + ../plugins/tiles/target/apidocs + docs/struts2-plugins/struts2-tiles-plugin/apidocs + + + ../plugins/velocity/target/apidocs + docs/struts2-plugins/struts2-velocity-plugin/apidocs + + + ../plugins/xslt/target/apidocs + docs/struts2-plugins/struts2-xslt-plugin/apidocs + - - - ../ - src/ - - pom.xml - src/ - - - - ../apps - src/apps - - pom.xml - src/ - - - - ../apps/showcase - src/apps/showcase - - pom.xml - src/ - - - - ../apps/rest-showcase - src/apps/rest-showcase - - pom.xml - src/ - - - - ../assembly - src/assembly - - pom.xml - src/ - - - - ../core - src/core - - pom.xml - src/ - - - - ../plugins - src/plugins - - */target/** - target/** - - - + + + ../ + src/ + + pom.xml + src/ + + + + ../apps + src/apps + + pom.xml + src/ + + + + ../apps/showcase + src/apps/showcase + + pom.xml + src/ + + + + ../apps/rest-showcase + src/apps/rest-showcase + + pom.xml + src/ + + + + ../assembly + src/assembly + + pom.xml + src/ + + + + ../core + src/core + + pom.xml + src/ + + + + ../plugins + src/plugins + + */target/** + target/** + + + diff --git a/assembly/src/main/assembly/apps.xml b/assembly/src/main/assembly/apps.xml index 37ec61afd3..43ade2f482 100644 --- a/assembly/src/main/assembly/apps.xml +++ b/assembly/src/main/assembly/apps.xml @@ -1,7 +1,6 @@ + - @@ -31,12 +29,6 @@ - - - ../xwork-core/target/apidocs - docs/xwork-core/apidocs - - ../target/site @@ -49,11 +41,15 @@ - target/cwiki + target/docs docs/docs + + ../plugins/async/target/apidocs + docs/struts2-plugins/struts2-async/apidocs + ../plugins/bean-validation/target/apidocs docs/struts2-plugins/struts2-bean-validation/apidocs @@ -70,18 +66,6 @@ ../plugins/convention/target/apidocs docs/struts2-plugins/struts2-convention-plugin/apidocs - - ../plugins/dwr/target/apidocs - docs/struts2-plugins/struts2-dwr-plugin/apidocs - - - ../plugins/embeddedjsp/target/apidocs - docs/struts2-plugins/struts2-embeddedjsp-plugin/apidocs - - - ../plugins/gxp/target/apidocs - docs/struts2-plugins/struts2-gxp-plugin/apidocs - ../plugins/jasperreports/target/apidocs docs/struts2-plugins/struts2-jasperreports-plugin/apidocs @@ -102,42 +86,10 @@ ../plugins/junit/target/apidocs docs/struts2-plugins/struts2-junit-plugin/apidocs - - ../plugins/osgi/target/apidocs - docs/struts2-plugins/struts2-osgi-plugin/apidocs - - - ../plugins/oval/target/apidocs - docs/struts2-plugins/struts2-oval-plugin/apidocs - - - ../plugins/pell-multipart/target/apidocs - docs/struts2-plugins/struts2-pell-multipart-plugin/apidocs - - - ../plugins/plexus/target/apidocs - docs/struts2-plugins/struts2-plexus-plugin/apidocs - - - ../plugins/portlet/target/apidocs - docs/struts2-plugins/struts2-portlet-plugin/apidocs - - - ../plugins/portlet-tiles/target/apidocs - docs/struts2-plugins/struts2-portlet-tiles-plugin/apidocs - ../plugins/rest/target/apidocs docs/struts2-plugins/struts2-rest-plugin/apidocs - - ../plugins/sitegraph/target/apidocs - docs/struts2-plugins/struts2-sitegraph-plugin/apidocs - - - ../plugins/sitemesh/target/apidocs - docs/struts2-plugins/struts2-sitemesh-plugin/apidocs - ../plugins/spring/target/apidocs docs/struts2-plugins/struts2-spring-plugin/apidocs @@ -150,6 +102,14 @@ ../plugins/tiles/target/apidocs docs/struts2-plugins/struts2-tiles-plugin/apidocs + + ../plugins/velocity/target/apidocs + docs/struts2-plugins/struts2-velocity-plugin/apidocs + + + ../plugins/xslt/target/apidocs + docs/struts2-plugins/struts2-xslt-plugin/apidocs + diff --git a/assembly/src/main/assembly/lib.xml b/assembly/src/main/assembly/lib.xml index e25418d122..073866ade9 100644 --- a/assembly/src/main/assembly/lib.xml +++ b/assembly/src/main/assembly/lib.xml @@ -1,7 +1,6 @@ + - @@ -58,13 +56,6 @@ OGNL-LICENSE.txt - - ../plugins/plexus/src/main/resources - - - CLASSWORLDS-LICENSE.txt - - ../plugins/rest/src/main/resources @@ -73,20 +64,5 @@ XPP3-LICENSE.txt - - ../plugins/sitemesh/src/main/resources - - - SITEMESH-LICENSE.txt - - - - ../plugins/oval/src/main/resources - - - OVAL-LICENSE.txt - XSTREAM-LICENSE.txt - - diff --git a/assembly/src/main/assembly/min-lib.xml b/assembly/src/main/assembly/min-lib.xml index f139dd07c2..9c51fb418f 100644 --- a/assembly/src/main/assembly/min-lib.xml +++ b/assembly/src/main/assembly/min-lib.xml @@ -1,7 +1,6 @@ + - @@ -38,11 +36,13 @@ org.apache.struts:struts2-core org.freemarker:freemarker org.apache.commons:commons-lang3 + org.apache.commons:commons-text org.apache.logging.log4j:log4j-api ognl:ognl + org.apache.commons:commons-fileupload2-jakarta + org.apache.commons:commons-io + com.github.ben-manes.caffeine:caffeine org.javassist:javassist - commons-fileupload:commons-fileupload - commons-io:commons-io diff --git a/assembly/src/main/assembly/src.xml b/assembly/src/main/assembly/src.xml index c520129eec..b70ea518ab 100644 --- a/assembly/src/main/assembly/src.xml +++ b/assembly/src/main/assembly/src.xml @@ -1,7 +1,6 @@ + - @@ -50,14 +48,6 @@ src/ - - ../api - src/api - - pom.xml - src/ - - ../apps src/apps @@ -109,14 +99,6 @@ *.iws - - ../bundles - src/bundles - - */target/** - target/** - - diff --git a/assembly/src/main/resources/NOTICE.txt b/assembly/src/main/resources/NOTICE.txt index 3e10af8898..cec81a249a 100644 --- a/assembly/src/main/resources/NOTICE.txt +++ b/assembly/src/main/resources/NOTICE.txt @@ -11,7 +11,6 @@ ANTLR (http://www.antlr.org/). Classworlds (http://classworlds.codehaus.org/). EZMorph (http://ezmorph.sourceforge.net/) FreeMarker (http://freemarker.org/). -JSON-lib (http://json-lib.sourceforge.net/). OGNL (http://www.opensymphony.com/ognl/). Plexus (http://plexus.codehaus.org/). SiteMesh (http://www.opensymphony.com/sitemesh/). diff --git a/assembly/src/main/resources/build.xml b/assembly/src/main/resources/build.xml index d271ab66dd..2c27d6bb29 100644 --- a/assembly/src/main/resources/build.xml +++ b/assembly/src/main/resources/build.xml @@ -1,4 +1,24 @@ - + + diff --git a/assembly/src/main/resources/docs-urls.txt b/assembly/src/main/resources/docs-urls.txt new file mode 100644 index 0000000000..d96c3ea236 --- /dev/null +++ b/assembly/src/main/resources/docs-urls.txt @@ -0,0 +1,6 @@ +https://struts.apache.org/getting-started/ +https://struts.apache.org/security/ +https://struts.apache.org/core-developers/ +https://struts.apache.org/tag-developers/ +https://struts.apache.org/maven-archetypes/ +https://struts.apache.org/plugins/ diff --git a/assembly/src/main/resources/template.vm b/assembly/src/main/resources/template.vm index e254e59a00..07189c0609 100644 --- a/assembly/src/main/resources/template.vm +++ b/assembly/src/main/resources/template.vm @@ -1,6 +1,6 @@ #set ($stylebase = "https://struts.apache.org/css") - @@ -43,12 +43,12 @@ under the License. #end - #end - - - - - - -
    -
    -
    - Welcome to the OSGi console! Type 'help' to see the list of available commands. -
    -
    - <@s.url var="execUrl" namespace="/osgi/admin" action="execCommand" /> - - -
    -
    - - diff --git a/bundles/admin/src/main/resources/osgi/admin/viewBundle.ftl b/bundles/admin/src/main/resources/osgi/admin/viewBundle.ftl deleted file mode 100644 index 13a1ae864a..0000000000 --- a/bundles/admin/src/main/resources/osgi/admin/viewBundle.ftl +++ /dev/null @@ -1,147 +0,0 @@ - - - ${bundle.symbolicName!} - - " /> - " /> - - - - - - - - - - - -<@s.actionerror /> - -
    - -
    - - - - - - - - - - - - - - - - - -
    Id${bundle.bundleId!}
    Name${bundle.symbolicName!}
    Location${bundle.location!}
    Status${action.getBundleState(bundle)}
    -
    -
    - <#list (bundle.registeredServices)! as service> - - <#list (service.propertyKeys)! as key > - - - - - -
    ${key}${action.displayProperty(service.getProperty(key))}
    -
    - -
    -
    - <#list (bundle.servicesInUse)! as service> - - <#list (service.propertyKeys)! as key > - - - - - -
    ${key}${action.displayProperty(service.getProperty(key))!}
    -
    - -
    -
    - <#list packages! as pkg> - - - - - - - - - -
    Name${pkg.name}
    Actions -
      - <#list (pkg.actionConfigs.keySet())! as name > -
    • ${name}
    • - -
    -
    -
    - -
    -
    - - <#list headerKeys as header> - - - - - -
    ${header}
    ${bundle.headers.get(header)}
    -
    -
    - - \ No newline at end of file diff --git a/bundles/admin/src/main/resources/osgi/admin/viewBundles.ftl b/bundles/admin/src/main/resources/osgi/admin/viewBundles.ftl deleted file mode 100644 index 96ee51b19f..0000000000 --- a/bundles/admin/src/main/resources/osgi/admin/viewBundles.ftl +++ /dev/null @@ -1,71 +0,0 @@ - - - OSGi Bundles - - " /> - " /> - - - - - - - - - - - - - - - - - - <#list bundles as bundle> - - - - - - - - -
    NameStatusStruts BundleActions
    - ${bundle.symbolicName} - ${action.getBundleState(bundle)}${action.isStrutsEnabled(bundle)?string("yes", "no")} - <#if action.isAllowedAction(bundle, "start")> - - - Start - - - - <#if action.isAllowedAction(bundle, "stop")> - - - Stop - - - - <#if action.isAllowedAction(bundle, "update")> - - - Update - - -
    - - diff --git a/bundles/admin/src/main/resources/static/css/main.css b/bundles/admin/src/main/resources/static/css/main.css deleted file mode 100644 index 985aba8faf..0000000000 --- a/bundles/admin/src/main/resources/static/css/main.css +++ /dev/null @@ -1,103 +0,0 @@ -.right { - clear: both; - float: right; -} - -.left { - clear: both; - float: left; -} - -.bundleDetails td { - border: 1px solid #C8C8C8; -} - -.rowTitle { - width: 141px; - font-weight: bold; - vertical-align: top; -} - -table.properties { - border-style: solid; - border-width: 1px; - border-color: #3366CC; -} - -table.properties td { - border-style: solid; - border-width: 1px; - border-color: #3366CC; -} - -table.properties td.name { - background-color: #C3D9FF; - vertical-align: top; -} - -table.properties th { - background-color: #C3D9FF; -} - -img { - border-style: none; -} - -.fg-button { - outline: 0; - margin: 0 4px 0 0; - padding: .4em 1em; - text-decoration: none !important; - cursor: pointer; - position: relative; - text-align: center; - zoom: 1; -} - -.fg-button .ui-icon { - margin-left: -3px; - margin-top: -8px; - position: absolute; - top: 50%; -} - -.fg-button-small { - outline: 0; - margin: 0 4px 0 0; - padding: 0em 1em; - text-decoration: none !important; - cursor: pointer; - position: relative; - text-align: center; -} - -.fg-button-small .ui-icon { - margin-left: -3px; - margin-top: -8px; - position: absolute; - top: 50%; -} - -.fg-button-icon-left .ui-icon { - left: 0em; - margin-left: 0; - right: auto; -} - -.menu { - clear: both; - padding-bottom: 10px; - height:25px; -} - -.tabs { - clear: both; -} - -.propertyValue { - width: 600px; - overflow: auto; -} - - - diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png deleted file mode 100644 index 5b5dab2ab7..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_flat_0_aaaaaa_40x100.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png deleted file mode 100644 index 47acaadd73..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_flat_55_fbec88_40x100.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png deleted file mode 100644 index 9fb564f8d0..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_glass_75_d0e5f5_1x400.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png deleted file mode 100644 index 014951529c..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_glass_85_dfeffc_1x400.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png deleted file mode 100644 index 4443fdc1a1..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_glass_95_fef1ec_1x400.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png deleted file mode 100644 index 0cdbda36a5..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_gloss-wave_55_5c9ccc_500x100.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png deleted file mode 100644 index f7cc01623a..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_inset-hard_100_f5f8f9_1x100.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png deleted file mode 100644 index 38c38335d0..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-bg_inset-hard_100_fcfdfd_1x100.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_217bc0_256x240.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_217bc0_256x240.png deleted file mode 100644 index 0d979071be..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_217bc0_256x240.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_2e83ff_256x240.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_2e83ff_256x240.png deleted file mode 100644 index b425c446d2..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_2e83ff_256x240.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_469bdd_256x240.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_469bdd_256x240.png deleted file mode 100644 index 5e7915fa70..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_469bdd_256x240.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_6da8d5_256x240.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_6da8d5_256x240.png deleted file mode 100644 index 60e20ca189..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_6da8d5_256x240.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_cd0a0a_256x240.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_cd0a0a_256x240.png deleted file mode 100644 index 2db88b796a..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_cd0a0a_256x240.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_d8e7f3_256x240.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_d8e7f3_256x240.png deleted file mode 100644 index 8da5e0a8fe..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_d8e7f3_256x240.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_f9bd01_256x240.png b/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_f9bd01_256x240.png deleted file mode 100644 index 2fb5ba505a..0000000000 Binary files a/bundles/admin/src/main/resources/static/css/redmond/images/ui-icons_f9bd01_256x240.png and /dev/null differ diff --git a/bundles/admin/src/main/resources/static/css/redmond/jquery-ui-1.7.1.custom.css b/bundles/admin/src/main/resources/static/css/redmond/jquery-ui-1.7.1.custom.css deleted file mode 100644 index 3e15a2e15e..0000000000 --- a/bundles/admin/src/main/resources/static/css/redmond/jquery-ui-1.7.1.custom.css +++ /dev/null @@ -1,404 +0,0 @@ -/* -* jQuery UI CSS Framework -* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) -* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. -*/ - -/* Layout helpers -----------------------------------*/ -.ui-helper-hidden { display: none; } -.ui-helper-hidden-accessible { position: absolute; left: -99999999px; } -.ui-helper-reset { margin: 0; padding: 0; border: 0; outline: 0; line-height: 1.3; text-decoration: none; font-size: 100%; list-style: none; } -.ui-helper-clearfix:after { content: "."; display: block; height: 0; clear: both; visibility: hidden; } -.ui-helper-clearfix { display: inline-block; } -/* required comment for clearfix to work in Opera \*/ -* html .ui-helper-clearfix { height:1%; } -.ui-helper-clearfix { display:block; } -/* end clearfix */ -.ui-helper-zfix { width: 100%; height: 100%; top: 0; left: 0; position: absolute; opacity: 0; filter:Alpha(Opacity=0); } - - -/* Interaction Cues -----------------------------------*/ -.ui-state-disabled { cursor: default !important; } - - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { display: block; text-indent: -99999px; overflow: hidden; background-repeat: no-repeat; } - - -/* Misc visuals -----------------------------------*/ - -/* Overlays */ -.ui-widget-overlay { position: absolute; top: 0; left: 0; width: 100%; height: 100%; } - -/* -* jQuery UI CSS Framework -* Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) -* Dual licensed under the MIT (MIT-LICENSE.txt) and GPL (GPL-LICENSE.txt) licenses. -* To view and modify this theme, visit http://jqueryui.com/themeroller/?ffDefault=Lucida%20Grande,%20Lucida%20Sans,%20Arial,%20sans-serif&fwDefault=bold&fsDefault=1.1em&cornerRadius=5px&bgColorHeader=5c9ccc&bgTextureHeader=12_gloss_wave.png&bgImgOpacityHeader=55&borderColorHeader=4297d7&fcHeader=ffffff&iconColorHeader=d8e7f3&bgColorContent=fcfdfd&bgTextureContent=06_inset_hard.png&bgImgOpacityContent=100&borderColorContent=a6c9e2&fcContent=222222&iconColorContent=469bdd&bgColorDefault=dfeffc&bgTextureDefault=02_glass.png&bgImgOpacityDefault=85&borderColorDefault=c5dbec&fcDefault=2e6e9e&iconColorDefault=6da8d5&bgColorHover=d0e5f5&bgTextureHover=02_glass.png&bgImgOpacityHover=75&borderColorHover=79b7e7&fcHover=1d5987&iconColorHover=217bc0&bgColorActive=f5f8f9&bgTextureActive=06_inset_hard.png&bgImgOpacityActive=100&borderColorActive=79b7e7&fcActive=e17009&iconColorActive=f9bd01&bgColorHighlight=fbec88&bgTextureHighlight=01_flat.png&bgImgOpacityHighlight=55&borderColorHighlight=fad42e&fcHighlight=363636&iconColorHighlight=2e83ff&bgColorError=fef1ec&bgTextureError=02_glass.png&bgImgOpacityError=95&borderColorError=cd0a0a&fcError=cd0a0a&iconColorError=cd0a0a&bgColorOverlay=aaaaaa&bgTextureOverlay=01_flat.png&bgImgOpacityOverlay=0&opacityOverlay=30&bgColorShadow=aaaaaa&bgTextureShadow=01_flat.png&bgImgOpacityShadow=0&opacityShadow=30&thicknessShadow=8px&offsetTopShadow=-8px&offsetLeftShadow=-8px&cornerRadiusShadow=8px -*/ - - -/* Component containers -----------------------------------*/ -.ui-widget { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1.1em; } -.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button { font-family: Lucida Grande, Lucida Sans, Arial, sans-serif; font-size: 1em; } -.ui-widget-content { border: 1px solid #a6c9e2; background: #fcfdfd url(images/ui-bg_inset-hard_100_fcfdfd_1x100.png) 50% bottom repeat-x; color: #222222; } -.ui-widget-content a { color: #222222; } -.ui-widget-header { border: 1px solid #4297d7; background: #5c9ccc url(images/ui-bg_gloss-wave_55_5c9ccc_500x100.png) 50% 50% repeat-x; color: #ffffff; font-weight: bold; } -.ui-widget-header a { color: #ffffff; } - -/* Interaction states -----------------------------------*/ -.ui-state-default, .ui-widget-content .ui-state-default { border: 1px solid #c5dbec; background: #dfeffc url(images/ui-bg_glass_85_dfeffc_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #2e6e9e; outline: none; } -.ui-state-default a, .ui-state-default a:link, .ui-state-default a:visited { color: #2e6e9e; text-decoration: none; outline: none; } -.ui-state-hover, .ui-widget-content .ui-state-hover, .ui-state-focus, .ui-widget-content .ui-state-focus { border: 1px solid #79b7e7; background: #d0e5f5 url(images/ui-bg_glass_75_d0e5f5_1x400.png) 50% 50% repeat-x; font-weight: bold; color: #1d5987; outline: none; } -.ui-state-hover a, .ui-state-hover a:hover { color: #1d5987; text-decoration: none; outline: none; } -.ui-state-active, .ui-widget-content .ui-state-active { border: 1px solid #79b7e7; background: #f5f8f9 url(images/ui-bg_inset-hard_100_f5f8f9_1x100.png) 50% 50% repeat-x; font-weight: bold; color: #e17009; outline: none; } -.ui-state-active a, .ui-state-active a:link, .ui-state-active a:visited { color: #e17009; outline: none; text-decoration: none; } - -/* Interaction Cues -----------------------------------*/ -.ui-state-highlight, .ui-widget-content .ui-state-highlight {border: 1px solid #fad42e; background: #fbec88 url(images/ui-bg_flat_55_fbec88_40x100.png) 50% 50% repeat-x; color: #363636; } -.ui-state-highlight a, .ui-widget-content .ui-state-highlight a { color: #363636; } -.ui-state-error, .ui-widget-content .ui-state-error {border: 1px solid #cd0a0a; background: #fef1ec url(images/ui-bg_glass_95_fef1ec_1x400.png) 50% 50% repeat-x; color: #cd0a0a; } -.ui-state-error a, .ui-widget-content .ui-state-error a { color: #cd0a0a; } -.ui-state-error-text, .ui-widget-content .ui-state-error-text { color: #cd0a0a; } -.ui-state-disabled, .ui-widget-content .ui-state-disabled { opacity: .35; filter:Alpha(Opacity=35); background-image: none; } -.ui-priority-primary, .ui-widget-content .ui-priority-primary { font-weight: bold; } -.ui-priority-secondary, .ui-widget-content .ui-priority-secondary { opacity: .7; filter:Alpha(Opacity=70); font-weight: normal; } - -/* Icons -----------------------------------*/ - -/* states and images */ -.ui-icon { width: 16px; height: 16px; background-image: url(images/ui-icons_469bdd_256x240.png); } -.ui-widget-content .ui-icon {background-image: url(images/ui-icons_469bdd_256x240.png); } -.ui-widget-header .ui-icon {background-image: url(images/ui-icons_d8e7f3_256x240.png); } -.ui-state-default .ui-icon { background-image: url(images/ui-icons_6da8d5_256x240.png); } -.ui-state-hover .ui-icon, .ui-state-focus .ui-icon {background-image: url(images/ui-icons_217bc0_256x240.png); } -.ui-state-active .ui-icon {background-image: url(images/ui-icons_f9bd01_256x240.png); } -.ui-state-highlight .ui-icon {background-image: url(images/ui-icons_2e83ff_256x240.png); } -.ui-state-error .ui-icon, .ui-state-error-text .ui-icon {background-image: url(images/ui-icons_cd0a0a_256x240.png); } - -/* positioning */ -.ui-icon-carat-1-n { background-position: 0 0; } -.ui-icon-carat-1-ne { background-position: -16px 0; } -.ui-icon-carat-1-e { background-position: -32px 0; } -.ui-icon-carat-1-se { background-position: -48px 0; } -.ui-icon-carat-1-s { background-position: -64px 0; } -.ui-icon-carat-1-sw { background-position: -80px 0; } -.ui-icon-carat-1-w { background-position: -96px 0; } -.ui-icon-carat-1-nw { background-position: -112px 0; } -.ui-icon-carat-2-n-s { background-position: -128px 0; } -.ui-icon-carat-2-e-w { background-position: -144px 0; } -.ui-icon-triangle-1-n { background-position: 0 -16px; } -.ui-icon-triangle-1-ne { background-position: -16px -16px; } -.ui-icon-triangle-1-e { background-position: -32px -16px; } -.ui-icon-triangle-1-se { background-position: -48px -16px; } -.ui-icon-triangle-1-s { background-position: -64px -16px; } -.ui-icon-triangle-1-sw { background-position: -80px -16px; } -.ui-icon-triangle-1-w { background-position: -96px -16px; } -.ui-icon-triangle-1-nw { background-position: -112px -16px; } -.ui-icon-triangle-2-n-s { background-position: -128px -16px; } -.ui-icon-triangle-2-e-w { background-position: -144px -16px; } -.ui-icon-arrow-1-n { background-position: 0 -32px; } -.ui-icon-arrow-1-ne { background-position: -16px -32px; } -.ui-icon-arrow-1-e { background-position: -32px -32px; } -.ui-icon-arrow-1-se { background-position: -48px -32px; } -.ui-icon-arrow-1-s { background-position: -64px -32px; } -.ui-icon-arrow-1-sw { background-position: -80px -32px; } -.ui-icon-arrow-1-w { background-position: -96px -32px; } -.ui-icon-arrow-1-nw { background-position: -112px -32px; } -.ui-icon-arrow-2-n-s { background-position: -128px -32px; } -.ui-icon-arrow-2-ne-sw { background-position: -144px -32px; } -.ui-icon-arrow-2-e-w { background-position: -160px -32px; } -.ui-icon-arrow-2-se-nw { background-position: -176px -32px; } -.ui-icon-arrowstop-1-n { background-position: -192px -32px; } -.ui-icon-arrowstop-1-e { background-position: -208px -32px; } -.ui-icon-arrowstop-1-s { background-position: -224px -32px; } -.ui-icon-arrowstop-1-w { background-position: -240px -32px; } -.ui-icon-arrowthick-1-n { background-position: 0 -48px; } -.ui-icon-arrowthick-1-ne { background-position: -16px -48px; } -.ui-icon-arrowthick-1-e { background-position: -32px -48px; } -.ui-icon-arrowthick-1-se { background-position: -48px -48px; } -.ui-icon-arrowthick-1-s { background-position: -64px -48px; } -.ui-icon-arrowthick-1-sw { background-position: -80px -48px; } -.ui-icon-arrowthick-1-w { background-position: -96px -48px; } -.ui-icon-arrowthick-1-nw { background-position: -112px -48px; } -.ui-icon-arrowthick-2-n-s { background-position: -128px -48px; } -.ui-icon-arrowthick-2-ne-sw { background-position: -144px -48px; } -.ui-icon-arrowthick-2-e-w { background-position: -160px -48px; } -.ui-icon-arrowthick-2-se-nw { background-position: -176px -48px; } -.ui-icon-arrowthickstop-1-n { background-position: -192px -48px; } -.ui-icon-arrowthickstop-1-e { background-position: -208px -48px; } -.ui-icon-arrowthickstop-1-s { background-position: -224px -48px; } -.ui-icon-arrowthickstop-1-w { background-position: -240px -48px; } -.ui-icon-arrowreturnthick-1-w { background-position: 0 -64px; } -.ui-icon-arrowreturnthick-1-n { background-position: -16px -64px; } -.ui-icon-arrowreturnthick-1-e { background-position: -32px -64px; } -.ui-icon-arrowreturnthick-1-s { background-position: -48px -64px; } -.ui-icon-arrowreturn-1-w { background-position: -64px -64px; } -.ui-icon-arrowreturn-1-n { background-position: -80px -64px; } -.ui-icon-arrowreturn-1-e { background-position: -96px -64px; } -.ui-icon-arrowreturn-1-s { background-position: -112px -64px; } -.ui-icon-arrowrefresh-1-w { background-position: -128px -64px; } -.ui-icon-arrowrefresh-1-n { background-position: -144px -64px; } -.ui-icon-arrowrefresh-1-e { background-position: -160px -64px; } -.ui-icon-arrowrefresh-1-s { background-position: -176px -64px; } -.ui-icon-arrow-4 { background-position: 0 -80px; } -.ui-icon-arrow-4-diag { background-position: -16px -80px; } -.ui-icon-extlink { background-position: -32px -80px; } -.ui-icon-newwin { background-position: -48px -80px; } -.ui-icon-refresh { background-position: -64px -80px; } -.ui-icon-shuffle { background-position: -80px -80px; } -.ui-icon-transfer-e-w { background-position: -96px -80px; } -.ui-icon-transferthick-e-w { background-position: -112px -80px; } -.ui-icon-folder-collapsed { background-position: 0 -96px; } -.ui-icon-folder-open { background-position: -16px -96px; } -.ui-icon-document { background-position: -32px -96px; } -.ui-icon-document-b { background-position: -48px -96px; } -.ui-icon-note { background-position: -64px -96px; } -.ui-icon-mail-closed { background-position: -80px -96px; } -.ui-icon-mail-open { background-position: -96px -96px; } -.ui-icon-suitcase { background-position: -112px -96px; } -.ui-icon-comment { background-position: -128px -96px; } -.ui-icon-person { background-position: -144px -96px; } -.ui-icon-print { background-position: -160px -96px; } -.ui-icon-trash { background-position: -176px -96px; } -.ui-icon-locked { background-position: -192px -96px; } -.ui-icon-unlocked { background-position: -208px -96px; } -.ui-icon-bookmark { background-position: -224px -96px; } -.ui-icon-tag { background-position: -240px -96px; } -.ui-icon-home { background-position: 0 -112px; } -.ui-icon-flag { background-position: -16px -112px; } -.ui-icon-calendar { background-position: -32px -112px; } -.ui-icon-cart { background-position: -48px -112px; } -.ui-icon-pencil { background-position: -64px -112px; } -.ui-icon-clock { background-position: -80px -112px; } -.ui-icon-disk { background-position: -96px -112px; } -.ui-icon-calculator { background-position: -112px -112px; } -.ui-icon-zoomin { background-position: -128px -112px; } -.ui-icon-zoomout { background-position: -144px -112px; } -.ui-icon-search { background-position: -160px -112px; } -.ui-icon-wrench { background-position: -176px -112px; } -.ui-icon-gear { background-position: -192px -112px; } -.ui-icon-heart { background-position: -208px -112px; } -.ui-icon-star { background-position: -224px -112px; } -.ui-icon-link { background-position: -240px -112px; } -.ui-icon-cancel { background-position: 0 -128px; } -.ui-icon-plus { background-position: -16px -128px; } -.ui-icon-plusthick { background-position: -32px -128px; } -.ui-icon-minus { background-position: -48px -128px; } -.ui-icon-minusthick { background-position: -64px -128px; } -.ui-icon-close { background-position: -80px -128px; } -.ui-icon-closethick { background-position: -96px -128px; } -.ui-icon-key { background-position: -112px -128px; } -.ui-icon-lightbulb { background-position: -128px -128px; } -.ui-icon-scissors { background-position: -144px -128px; } -.ui-icon-clipboard { background-position: -160px -128px; } -.ui-icon-copy { background-position: -176px -128px; } -.ui-icon-contact { background-position: -192px -128px; } -.ui-icon-image { background-position: -208px -128px; } -.ui-icon-video { background-position: -224px -128px; } -.ui-icon-script { background-position: -240px -128px; } -.ui-icon-alert { background-position: 0 -144px; } -.ui-icon-info { background-position: -16px -144px; } -.ui-icon-notice { background-position: -32px -144px; } -.ui-icon-help { background-position: -48px -144px; } -.ui-icon-check { background-position: -64px -144px; } -.ui-icon-bullet { background-position: -80px -144px; } -.ui-icon-radio-off { background-position: -96px -144px; } -.ui-icon-radio-on { background-position: -112px -144px; } -.ui-icon-pin-w { background-position: -128px -144px; } -.ui-icon-pin-s { background-position: -144px -144px; } -.ui-icon-play { background-position: 0 -160px; } -.ui-icon-pause { background-position: -16px -160px; } -.ui-icon-seek-next { background-position: -32px -160px; } -.ui-icon-seek-prev { background-position: -48px -160px; } -.ui-icon-seek-end { background-position: -64px -160px; } -.ui-icon-seek-first { background-position: -80px -160px; } -.ui-icon-stop { background-position: -96px -160px; } -.ui-icon-eject { background-position: -112px -160px; } -.ui-icon-volume-off { background-position: -128px -160px; } -.ui-icon-volume-on { background-position: -144px -160px; } -.ui-icon-power { background-position: 0 -176px; } -.ui-icon-signal-diag { background-position: -16px -176px; } -.ui-icon-signal { background-position: -32px -176px; } -.ui-icon-battery-0 { background-position: -48px -176px; } -.ui-icon-battery-1 { background-position: -64px -176px; } -.ui-icon-battery-2 { background-position: -80px -176px; } -.ui-icon-battery-3 { background-position: -96px -176px; } -.ui-icon-circle-plus { background-position: 0 -192px; } -.ui-icon-circle-minus { background-position: -16px -192px; } -.ui-icon-circle-close { background-position: -32px -192px; } -.ui-icon-circle-triangle-e { background-position: -48px -192px; } -.ui-icon-circle-triangle-s { background-position: -64px -192px; } -.ui-icon-circle-triangle-w { background-position: -80px -192px; } -.ui-icon-circle-triangle-n { background-position: -96px -192px; } -.ui-icon-circle-arrow-e { background-position: -112px -192px; } -.ui-icon-circle-arrow-s { background-position: -128px -192px; } -.ui-icon-circle-arrow-w { background-position: -144px -192px; } -.ui-icon-circle-arrow-n { background-position: -160px -192px; } -.ui-icon-circle-zoomin { background-position: -176px -192px; } -.ui-icon-circle-zoomout { background-position: -192px -192px; } -.ui-icon-circle-check { background-position: -208px -192px; } -.ui-icon-circlesmall-plus { background-position: 0 -208px; } -.ui-icon-circlesmall-minus { background-position: -16px -208px; } -.ui-icon-circlesmall-close { background-position: -32px -208px; } -.ui-icon-squaresmall-plus { background-position: -48px -208px; } -.ui-icon-squaresmall-minus { background-position: -64px -208px; } -.ui-icon-squaresmall-close { background-position: -80px -208px; } -.ui-icon-grip-dotted-vertical { background-position: 0 -224px; } -.ui-icon-grip-dotted-horizontal { background-position: -16px -224px; } -.ui-icon-grip-solid-vertical { background-position: -32px -224px; } -.ui-icon-grip-solid-horizontal { background-position: -48px -224px; } -.ui-icon-gripsmall-diagonal-se { background-position: -64px -224px; } -.ui-icon-grip-diagonal-se { background-position: -80px -224px; } - - -/* Misc visuals -----------------------------------*/ - -/* Corner radius */ -.ui-corner-tl { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; } -.ui-corner-tr { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; } -.ui-corner-bl { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; } -.ui-corner-br { -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; } -.ui-corner-top { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; } -.ui-corner-bottom { -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; } -.ui-corner-right { -moz-border-radius-topright: 5px; -webkit-border-top-right-radius: 5px; -moz-border-radius-bottomright: 5px; -webkit-border-bottom-right-radius: 5px; } -.ui-corner-left { -moz-border-radius-topleft: 5px; -webkit-border-top-left-radius: 5px; -moz-border-radius-bottomleft: 5px; -webkit-border-bottom-left-radius: 5px; } -.ui-corner-all { -moz-border-radius: 5px; -webkit-border-radius: 5px; } - -/* Overlays */ -.ui-widget-overlay { background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); } -.ui-widget-shadow { margin: -8px 0 0 -8px; padding: 8px; background: #aaaaaa url(images/ui-bg_flat_0_aaaaaa_40x100.png) 50% 50% repeat-x; opacity: .30;filter:Alpha(Opacity=30); -moz-border-radius: 8px; -webkit-border-radius: 8px; }/* Accordion -----------------------------------*/ -.ui-accordion .ui-accordion-header { cursor: pointer; position: relative; margin-top: 1px; zoom: 1; } -.ui-accordion .ui-accordion-li-fix { display: inline; } -.ui-accordion .ui-accordion-header-active { border-bottom: 0 !important; } -.ui-accordion .ui-accordion-header a { display: block; font-size: 1em; padding: .5em .5em .5em 2.2em; } -.ui-accordion .ui-accordion-header .ui-icon { position: absolute; left: .5em; top: 50%; margin-top: -8px; } -.ui-accordion .ui-accordion-content { padding: 1em 2.2em; border-top: 0; margin-top: -2px; position: relative; top: 1px; margin-bottom: 2px; overflow: auto; display: none; } -.ui-accordion .ui-accordion-content-active { display: block; }/* Datepicker -----------------------------------*/ -.ui-datepicker { width: 17em; padding: .2em .2em 0; } -.ui-datepicker .ui-datepicker-header { position:relative; padding:.2em 0; } -.ui-datepicker .ui-datepicker-prev, .ui-datepicker .ui-datepicker-next { position:absolute; top: 2px; width: 1.8em; height: 1.8em; } -.ui-datepicker .ui-datepicker-prev-hover, .ui-datepicker .ui-datepicker-next-hover { top: 1px; } -.ui-datepicker .ui-datepicker-prev { left:2px; } -.ui-datepicker .ui-datepicker-next { right:2px; } -.ui-datepicker .ui-datepicker-prev-hover { left:1px; } -.ui-datepicker .ui-datepicker-next-hover { right:1px; } -.ui-datepicker .ui-datepicker-prev span, .ui-datepicker .ui-datepicker-next span { display: block; position: absolute; left: 50%; margin-left: -8px; top: 50%; margin-top: -8px; } -.ui-datepicker .ui-datepicker-title { margin: 0 2.3em; line-height: 1.8em; text-align: center; } -.ui-datepicker .ui-datepicker-title select { float:left; font-size:1em; margin:1px 0; } -.ui-datepicker select.ui-datepicker-month-year {width: 100%;} -.ui-datepicker select.ui-datepicker-month, -.ui-datepicker select.ui-datepicker-year { width: 49%;} -.ui-datepicker .ui-datepicker-title select.ui-datepicker-year { float: right; } -.ui-datepicker table {width: 100%; font-size: .9em; border-collapse: collapse; margin:0 0 .4em; } -.ui-datepicker th { padding: .7em .3em; text-align: center; font-weight: bold; border: 0; } -.ui-datepicker td { border: 0; padding: 1px; } -.ui-datepicker td span, .ui-datepicker td a { display: block; padding: .2em; text-align: right; text-decoration: none; } -.ui-datepicker .ui-datepicker-buttonpane { background-image: none; margin: .7em 0 0 0; padding:0 .2em; border-left: 0; border-right: 0; border-bottom: 0; } -.ui-datepicker .ui-datepicker-buttonpane button { float: right; margin: .5em .2em .4em; cursor: pointer; padding: .2em .6em .3em .6em; width:auto; overflow:visible; } -.ui-datepicker .ui-datepicker-buttonpane button.ui-datepicker-current { float:left; } - -/* with multiple calendars */ -.ui-datepicker.ui-datepicker-multi { width:auto; } -.ui-datepicker-multi .ui-datepicker-group { float:left; } -.ui-datepicker-multi .ui-datepicker-group table { width:95%; margin:0 auto .4em; } -.ui-datepicker-multi-2 .ui-datepicker-group { width:50%; } -.ui-datepicker-multi-3 .ui-datepicker-group { width:33.3%; } -.ui-datepicker-multi-4 .ui-datepicker-group { width:25%; } -.ui-datepicker-multi .ui-datepicker-group-last .ui-datepicker-header { border-left-width:0; } -.ui-datepicker-multi .ui-datepicker-group-middle .ui-datepicker-header { border-left-width:0; } -.ui-datepicker-multi .ui-datepicker-buttonpane { clear:left; } -.ui-datepicker-row-break { clear:both; width:100%; } - -/* RTL support */ -.ui-datepicker-rtl { direction: rtl; } -.ui-datepicker-rtl .ui-datepicker-prev { right: 2px; left: auto; } -.ui-datepicker-rtl .ui-datepicker-next { left: 2px; right: auto; } -.ui-datepicker-rtl .ui-datepicker-prev:hover { right: 1px; left: auto; } -.ui-datepicker-rtl .ui-datepicker-next:hover { left: 1px; right: auto; } -.ui-datepicker-rtl .ui-datepicker-buttonpane { clear:right; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button { float: left; } -.ui-datepicker-rtl .ui-datepicker-buttonpane button.ui-datepicker-current { float:right; } -.ui-datepicker-rtl .ui-datepicker-group { float:right; } -.ui-datepicker-rtl .ui-datepicker-group-last .ui-datepicker-header { border-right-width:0; border-left-width:1px; } -.ui-datepicker-rtl .ui-datepicker-group-middle .ui-datepicker-header { border-right-width:0; border-left-width:1px; } - -/* IE6 IFRAME FIX (taken from datepicker 1.5.3 */ -.ui-datepicker-cover { - display: none; /*sorry for IE5*/ - display/**/: block; /*sorry for IE5*/ - position: absolute; /*must have*/ - z-index: -1; /*must have*/ - filter: mask(); /*must have*/ - top: -4px; /*must have*/ - left: -4px; /*must have*/ - width: 200px; /*must have*/ - height: 200px; /*must have*/ -}/* Dialog -----------------------------------*/ -.ui-dialog { position: relative; padding: .2em; width: 300px; } -.ui-dialog .ui-dialog-titlebar { padding: .5em .3em .3em 1em; position: relative; } -.ui-dialog .ui-dialog-title { float: left; margin: .1em 0 .2em; } -.ui-dialog .ui-dialog-titlebar-close { position: absolute; right: .3em; top: 50%; width: 19px; margin: -10px 0 0 0; padding: 1px; height: 18px; } -.ui-dialog .ui-dialog-titlebar-close span { display: block; margin: 1px; } -.ui-dialog .ui-dialog-titlebar-close:hover, .ui-dialog .ui-dialog-titlebar-close:focus { padding: 0; } -.ui-dialog .ui-dialog-content { border: 0; padding: .5em 1em; background: none; overflow: auto; zoom: 1; } -.ui-dialog .ui-dialog-buttonpane { text-align: left; border-width: 1px 0 0 0; background-image: none; margin: .5em 0 0 0; padding: .3em 1em .5em .4em; } -.ui-dialog .ui-dialog-buttonpane button { float: right; margin: .5em .4em .5em 0; cursor: pointer; padding: .2em .6em .3em .6em; line-height: 1.4em; width:auto; overflow:visible; } -.ui-dialog .ui-resizable-se { width: 14px; height: 14px; right: 3px; bottom: 3px; } -.ui-draggable .ui-dialog-titlebar { cursor: move; } -/* Progressbar -----------------------------------*/ -.ui-progressbar { height:2em; text-align: left; } -.ui-progressbar .ui-progressbar-value {margin: -1px; height:100%; }/* Resizable -----------------------------------*/ -.ui-resizable { position: relative;} -.ui-resizable-handle { position: absolute;font-size: 0.1px;z-index: 99999; display: block;} -.ui-resizable-disabled .ui-resizable-handle, .ui-resizable-autohide .ui-resizable-handle { display: none; } -.ui-resizable-n { cursor: n-resize; height: 7px; width: 100%; top: -5px; left: 0px; } -.ui-resizable-s { cursor: s-resize; height: 7px; width: 100%; bottom: -5px; left: 0px; } -.ui-resizable-e { cursor: e-resize; width: 7px; right: -5px; top: 0px; height: 100%; } -.ui-resizable-w { cursor: w-resize; width: 7px; left: -5px; top: 0px; height: 100%; } -.ui-resizable-se { cursor: se-resize; width: 12px; height: 12px; right: 1px; bottom: 1px; } -.ui-resizable-sw { cursor: sw-resize; width: 9px; height: 9px; left: -5px; bottom: -5px; } -.ui-resizable-nw { cursor: nw-resize; width: 9px; height: 9px; left: -5px; top: -5px; } -.ui-resizable-ne { cursor: ne-resize; width: 9px; height: 9px; right: -5px; top: -5px;}/* Slider -----------------------------------*/ -.ui-slider { position: relative; text-align: left; } -.ui-slider .ui-slider-handle { position: absolute; z-index: 2; width: 1.2em; height: 1.2em; cursor: default; } -.ui-slider .ui-slider-range { position: absolute; z-index: 1; font-size: .7em; display: block; border: 0; } - -.ui-slider-horizontal { height: .8em; } -.ui-slider-horizontal .ui-slider-handle { top: -.3em; margin-left: -.6em; } -.ui-slider-horizontal .ui-slider-range { top: 0; height: 100%; } -.ui-slider-horizontal .ui-slider-range-min { left: 0; } -.ui-slider-horizontal .ui-slider-range-max { right: 0; } - -.ui-slider-vertical { width: .8em; height: 100px; } -.ui-slider-vertical .ui-slider-handle { left: -.3em; margin-left: 0; margin-bottom: -.6em; } -.ui-slider-vertical .ui-slider-range { left: 0; width: 100%; } -.ui-slider-vertical .ui-slider-range-min { bottom: 0; } -.ui-slider-vertical .ui-slider-range-max { top: 0; }/* Tabs -----------------------------------*/ -.ui-tabs { padding: .2em; zoom: 1; } -.ui-tabs .ui-tabs-nav { list-style: none; position: relative; padding: .2em .2em 0; } -.ui-tabs .ui-tabs-nav li { position: relative; float: left; border-bottom-width: 0 !important; margin: 0 .2em -1px 0; padding: 0; } -.ui-tabs .ui-tabs-nav li a { float: left; text-decoration: none; padding: .5em 1em; } -.ui-tabs .ui-tabs-nav li.ui-tabs-selected { padding-bottom: 1px; border-bottom-width: 0; } -.ui-tabs .ui-tabs-nav li.ui-tabs-selected a, .ui-tabs .ui-tabs-nav li.ui-state-disabled a, .ui-tabs .ui-tabs-nav li.ui-state-processing a { cursor: text; } -.ui-tabs .ui-tabs-nav li a, .ui-tabs.ui-tabs-collapsible .ui-tabs-nav li.ui-tabs-selected a { cursor: pointer; } /* first selector in group seems obsolete, but required to overcome bug in Opera applying cursor: text overall if defined elsewhere... */ -.ui-tabs .ui-tabs-panel { padding: 1em 1.4em; display: block; border-width: 0; background: none; } -.ui-tabs .ui-tabs-hide { display: none !important; } diff --git a/bundles/admin/src/main/resources/static/css/shell.css b/bundles/admin/src/main/resources/static/css/shell.css deleted file mode 100644 index cf22837ad2..0000000000 --- a/bundles/admin/src/main/resources/static/css/shell.css +++ /dev/null @@ -1,43 +0,0 @@ -/* - * $Id: webconsole.css 590812 2007-10-31 20:32:54Z apetrelli $ - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -#shell { - clear: both; -} - -.wc-results { - overflow: auto; - margin: 0px; - padding: 5px; - font-family: courier; - color: white; - background-color: black; - height: 400px; -} -.wc-results pre { - display: inline; -} -.wc-command { - margin: 0px; - font-family: courier; - color: white; - background-color: black; - width: 100%; -} diff --git a/bundles/admin/src/main/resources/static/js/jquery-1.3.2.min.js b/bundles/admin/src/main/resources/static/js/jquery-1.3.2.min.js deleted file mode 100644 index b1ae21d8b2..0000000000 --- a/bundles/admin/src/main/resources/static/js/jquery-1.3.2.min.js +++ /dev/null @@ -1,19 +0,0 @@ -/* - * jQuery JavaScript Library v1.3.2 - * http://jquery.com/ - * - * Copyright (c) 2009 John Resig - * Dual licensed under the MIT and GPL licenses. - * http://docs.jquery.com/License - * - * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009) - * Revision: 6246 - */ -(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("",""]||!O.indexOf("",""]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"","
    "]||!O.indexOf("",""]||(!O.indexOf("",""]||!O.indexOf("",""]||!o.support.htmlSerialize&&[1,"div
    ","
    "]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}}); -/* - * Sizzle CSS Selector Engine - v0.9.3 - * Copyright 2009, The Dojo Foundation - * Released under the MIT, BSD, and GPL Licenses. - * More information: http://sizzlejs.com/ - */ -(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return UT[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="

    ";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="
    ";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("
    ").append(M.responseText.replace(//g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='
    ';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})(); \ No newline at end of file diff --git a/bundles/admin/src/main/resources/static/js/jquery-ui-1.7.1.custom.min.js b/bundles/admin/src/main/resources/static/js/jquery-ui-1.7.1.custom.min.js deleted file mode 100644 index c50a6e1730..0000000000 --- a/bundles/admin/src/main/resources/static/js/jquery-ui-1.7.1.custom.min.js +++ /dev/null @@ -1,20 +0,0 @@ -/* - * jQuery UI 1.7.1 - * - * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://docs.jquery.com/UI - */ jQuery.ui||(function(c){var i=c.fn.remove,d=c.browser.mozilla&&(parseFloat(c.browser.version)<1.9);c.ui={version:"1.7.1",plugin:{add:function(k,l,n){var m=c.ui[k].prototype;for(var j in n){m.plugins[j]=m.plugins[j]||[];m.plugins[j].push([l,n[j]])}},call:function(j,l,k){var n=j.plugins[l];if(!n||!j.element[0].parentNode){return}for(var m=0;m0){return true}m[j]=1;l=(m[j]>0);m[j]=0;return l},isOverAxis:function(k,j,l){return(k>j)&&(k<(j+l))},isOver:function(o,k,n,m,j,l){return c.ui.isOverAxis(o,n,j)&&c.ui.isOverAxis(k,m,l)},keyCode:{BACKSPACE:8,CAPS_LOCK:20,COMMA:188,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38}};if(d){var f=c.attr,e=c.fn.removeAttr,h="http://www.w3.org/2005/07/aaa",a=/^aria-/,b=/^wairole:/;c.attr=function(k,j,l){var m=l!==undefined;return(j=="role"?(m?f.call(this,k,j,"wairole:"+l):(f.apply(this,arguments)||"").replace(b,"")):(a.test(j)?(m?k.setAttributeNS(h,j.replace(a,"aaa:"),l):f.call(this,k,j.replace(a,"aaa:"))):f.apply(this,arguments)))};c.fn.removeAttr=function(j){return(a.test(j)?this.each(function(){this.removeAttributeNS(h,j.replace(a,""))}):e.call(this,j))}}c.fn.extend({remove:function(){c("*",this).add(this).each(function(){c(this).triggerHandler("remove")});return i.apply(this,arguments)},enableSelection:function(){return this.attr("unselectable","off").css("MozUserSelect","").unbind("selectstart.ui")},disableSelection:function(){return this.attr("unselectable","on").css("MozUserSelect","none").bind("selectstart.ui",function(){return false})},scrollParent:function(){var j;if((c.browser.msie&&(/(static|relative)/).test(this.css("position")))||(/absolute/).test(this.css("position"))){j=this.parents().filter(function(){return(/(relative|absolute|fixed)/).test(c.curCSS(this,"position",1))&&(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}else{j=this.parents().filter(function(){return(/(auto|scroll)/).test(c.curCSS(this,"overflow",1)+c.curCSS(this,"overflow-y",1)+c.curCSS(this,"overflow-x",1))}).eq(0)}return(/fixed/).test(this.css("position"))||!j.length?c(document):j}});c.extend(c.expr[":"],{data:function(l,k,j){return !!c.data(l,j[3])},focusable:function(k){var l=k.nodeName.toLowerCase(),j=c.attr(k,"tabindex");return(/input|select|textarea|button|object/.test(l)?!k.disabled:"a"==l||"area"==l?k.href||!isNaN(j):!isNaN(j))&&!c(k)["area"==l?"parents":"closest"](":hidden").length},tabbable:function(k){var j=c.attr(k,"tabindex");return(isNaN(j)||j>=0)&&c(k).is(":focusable")}});function g(m,n,o,l){function k(q){var p=c[m][n][q]||[];return(typeof p=="string"?p.split(/,?\s+/):p)}var j=k("getter");if(l.length==1&&typeof l[0]=="string"){j=j.concat(k("getterSetter"))}return(c.inArray(o,j)!=-1)}c.widget=function(k,j){var l=k.split(".")[0];k=k.split(".")[1];c.fn[k]=function(p){var n=(typeof p=="string"),o=Array.prototype.slice.call(arguments,1);if(n&&p.substring(0,1)=="_"){return this}if(n&&g(l,k,p,o)){var m=c.data(this[0],k);return(m?m[p].apply(m,o):undefined)}return this.each(function(){var q=c.data(this,k);(!q&&!n&&c.data(this,k,new c[l][k](this,p))._init());(q&&n&&c.isFunction(q[p])&&q[p].apply(q,o))})};c[l]=c[l]||{};c[l][k]=function(o,n){var m=this;this.namespace=l;this.widgetName=k;this.widgetEventPrefix=c[l][k].eventPrefix||k;this.widgetBaseClass=l+"-"+k;this.options=c.extend({},c.widget.defaults,c[l][k].defaults,c.metadata&&c.metadata.get(o)[k],n);this.element=c(o).bind("setData."+k,function(q,p,r){if(q.target==o){return m._setData(p,r)}}).bind("getData."+k,function(q,p){if(q.target==o){return m._getData(p)}}).bind("remove",function(){return m.destroy()})};c[l][k].prototype=c.extend({},c.widget.prototype,j);c[l][k].getterSetter="option"};c.widget.prototype={_init:function(){},destroy:function(){this.element.removeData(this.widgetName).removeClass(this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").removeAttr("aria-disabled")},option:function(l,m){var k=l,j=this;if(typeof l=="string"){if(m===undefined){return this._getData(l)}k={};k[l]=m}c.each(k,function(n,o){j._setData(n,o)})},_getData:function(j){return this.options[j]},_setData:function(j,k){this.options[j]=k;if(j=="disabled"){this.element[k?"addClass":"removeClass"](this.widgetBaseClass+"-disabled "+this.namespace+"-state-disabled").attr("aria-disabled",k)}},enable:function(){this._setData("disabled",false)},disable:function(){this._setData("disabled",true)},_trigger:function(l,m,n){var p=this.options[l],j=(l==this.widgetEventPrefix?l:this.widgetEventPrefix+l);m=c.Event(m);m.type=j;if(m.originalEvent){for(var k=c.event.props.length,o;k;){o=c.event.props[--k];m[o]=m.originalEvent[o]}}this.element.trigger(m,n);return !(c.isFunction(p)&&p.call(this.element[0],m,n)===false||m.isDefaultPrevented())}};c.widget.defaults={disabled:false};c.ui.mouse={_mouseInit:function(){var j=this;this.element.bind("mousedown."+this.widgetName,function(k){return j._mouseDown(k)}).bind("click."+this.widgetName,function(k){if(j._preventClickEvent){j._preventClickEvent=false;k.stopImmediatePropagation();return false}});if(c.browser.msie){this._mouseUnselectable=this.element.attr("unselectable");this.element.attr("unselectable","on")}this.started=false},_mouseDestroy:function(){this.element.unbind("."+this.widgetName);(c.browser.msie&&this.element.attr("unselectable",this._mouseUnselectable))},_mouseDown:function(l){l.originalEvent=l.originalEvent||{};if(l.originalEvent.mouseHandled){return}(this._mouseStarted&&this._mouseUp(l));this._mouseDownEvent=l;var k=this,m=(l.which==1),j=(typeof this.options.cancel=="string"?c(l.target).parents().add(l.target).filter(this.options.cancel).length:false);if(!m||j||!this._mouseCapture(l)){return true}this.mouseDelayMet=!this.options.delay;if(!this.mouseDelayMet){this._mouseDelayTimer=setTimeout(function(){k.mouseDelayMet=true},this.options.delay)}if(this._mouseDistanceMet(l)&&this._mouseDelayMet(l)){this._mouseStarted=(this._mouseStart(l)!==false);if(!this._mouseStarted){l.preventDefault();return true}}this._mouseMoveDelegate=function(n){return k._mouseMove(n)};this._mouseUpDelegate=function(n){return k._mouseUp(n)};c(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate);(c.browser.safari||l.preventDefault());l.originalEvent.mouseHandled=true;return true},_mouseMove:function(j){if(c.browser.msie&&!j.button){return this._mouseUp(j)}if(this._mouseStarted){this._mouseDrag(j);return j.preventDefault()}if(this._mouseDistanceMet(j)&&this._mouseDelayMet(j)){this._mouseStarted=(this._mouseStart(this._mouseDownEvent,j)!==false);(this._mouseStarted?this._mouseDrag(j):this._mouseUp(j))}return !this._mouseStarted},_mouseUp:function(j){c(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate);if(this._mouseStarted){this._mouseStarted=false;this._preventClickEvent=(j.target==this._mouseDownEvent.target);this._mouseStop(j)}return false},_mouseDistanceMet:function(j){return(Math.max(Math.abs(this._mouseDownEvent.pageX-j.pageX),Math.abs(this._mouseDownEvent.pageY-j.pageY))>=this.options.distance)},_mouseDelayMet:function(j){return this.mouseDelayMet},_mouseStart:function(j){},_mouseDrag:function(j){},_mouseStop:function(j){},_mouseCapture:function(j){return true}};c.ui.mouse.defaults={cancel:null,distance:1,delay:0}})(jQuery);;/* - * jQuery UI Tabs 1.7.1 - * - * Copyright (c) 2009 AUTHORS.txt (http://jqueryui.com/about) - * Dual licensed under the MIT (MIT-LICENSE.txt) - * and GPL (GPL-LICENSE.txt) licenses. - * - * http://docs.jquery.com/UI/Tabs - * - * Depends: - * ui.core.js - */ (function(a){a.widget("ui.tabs",{_init:function(){if(this.options.deselectable!==undefined){this.options.collapsible=this.options.deselectable}this._tabify(true)},_setData:function(b,c){if(b=="selected"){if(this.options.collapsible&&c==this.options.selected){return}this.select(c)}else{this.options[b]=c;if(b=="deselectable"){this.options.collapsible=c}this._tabify()}},_tabId:function(b){return b.title&&b.title.replace(/\s/g,"_").replace(/[^A-Za-z0-9\-_:\.]/g,"")||this.options.idPrefix+a.data(b)},_sanitizeSelector:function(b){return b.replace(/:/g,"\\:")},_cookie:function(){var b=this.cookie||(this.cookie=this.options.cookie.name||"ui-tabs-"+a.data(this.list[0]));return a.cookie.apply(null,[b].concat(a.makeArray(arguments)))},_ui:function(c,b){return{tab:c,panel:b,index:this.anchors.index(c)}},_cleanup:function(){this.lis.filter(".ui-state-processing").removeClass("ui-state-processing").find("span:data(label.tabs)").each(function(){var b=a(this);b.html(b.data("label.tabs")).removeData("label.tabs")})},_tabify:function(n){this.list=this.element.children("ul:first");this.lis=a("li:has(a[href])",this.list);this.anchors=this.lis.map(function(){return a("a",this)[0]});this.panels=a([]);var p=this,d=this.options;var c=/^#.+/;this.anchors.each(function(r,o){var q=a(o).attr("href");var s=q.split("#")[0],u;if(s&&(s===location.toString().split("#")[0]||(u=a("base")[0])&&s===u.href)){q=o.hash;o.href=q}if(c.test(q)){p.panels=p.panels.add(p._sanitizeSelector(q))}else{if(q!="#"){a.data(o,"href.tabs",q);a.data(o,"load.tabs",q.replace(/#.*$/,""));var w=p._tabId(o);o.href="#"+w;var v=a("#"+w);if(!v.length){v=a(d.panelTemplate).attr("id",w).addClass("ui-tabs-panel ui-widget-content ui-corner-bottom").insertAfter(p.panels[r-1]||p.list);v.data("destroy.tabs",true)}p.panels=p.panels.add(v)}else{d.disabled.push(r)}}});if(n){this.element.addClass("ui-tabs ui-widget ui-widget-content ui-corner-all");this.list.addClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.lis.addClass("ui-state-default ui-corner-top");this.panels.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom");if(d.selected===undefined){if(location.hash){this.anchors.each(function(q,o){if(o.hash==location.hash){d.selected=q;return false}})}if(typeof d.selected!="number"&&d.cookie){d.selected=parseInt(p._cookie(),10)}if(typeof d.selected!="number"&&this.lis.filter(".ui-tabs-selected").length){d.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))}d.selected=d.selected||0}else{if(d.selected===null){d.selected=-1}}d.selected=((d.selected>=0&&this.anchors[d.selected])||d.selected<0)?d.selected:0;d.disabled=a.unique(d.disabled.concat(a.map(this.lis.filter(".ui-state-disabled"),function(q,o){return p.lis.index(q)}))).sort();if(a.inArray(d.selected,d.disabled)!=-1){d.disabled.splice(a.inArray(d.selected,d.disabled),1)}this.panels.addClass("ui-tabs-hide");this.lis.removeClass("ui-tabs-selected ui-state-active");if(d.selected>=0&&this.anchors.length){this.panels.eq(d.selected).removeClass("ui-tabs-hide");this.lis.eq(d.selected).addClass("ui-tabs-selected ui-state-active");p.element.queue("tabs",function(){p._trigger("show",null,p._ui(p.anchors[d.selected],p.panels[d.selected]))});this.load(d.selected)}a(window).bind("unload",function(){p.lis.add(p.anchors).unbind(".tabs");p.lis=p.anchors=p.panels=null})}else{d.selected=this.lis.index(this.lis.filter(".ui-tabs-selected"))}this.element[d.collapsible?"addClass":"removeClass"]("ui-tabs-collapsible");if(d.cookie){this._cookie(d.selected,d.cookie)}for(var g=0,m;(m=this.lis[g]);g++){a(m)[a.inArray(g,d.disabled)!=-1&&!a(m).hasClass("ui-tabs-selected")?"addClass":"removeClass"]("ui-state-disabled")}if(d.cache===false){this.anchors.removeData("cache.tabs")}this.lis.add(this.anchors).unbind(".tabs");if(d.event!="mouseover"){var f=function(o,i){if(i.is(":not(.ui-state-disabled)")){i.addClass("ui-state-"+o)}};var j=function(o,i){i.removeClass("ui-state-"+o)};this.lis.bind("mouseover.tabs",function(){f("hover",a(this))});this.lis.bind("mouseout.tabs",function(){j("hover",a(this))});this.anchors.bind("focus.tabs",function(){f("focus",a(this).closest("li"))});this.anchors.bind("blur.tabs",function(){j("focus",a(this).closest("li"))})}var b,h;if(d.fx){if(a.isArray(d.fx)){b=d.fx[0];h=d.fx[1]}else{b=h=d.fx}}function e(i,o){i.css({display:""});if(a.browser.msie&&o.opacity){i[0].style.removeAttribute("filter")}}var k=h?function(i,o){a(i).closest("li").removeClass("ui-state-default").addClass("ui-tabs-selected ui-state-active");o.hide().removeClass("ui-tabs-hide").animate(h,h.duration||"normal",function(){e(o,h);p._trigger("show",null,p._ui(i,o[0]))})}:function(i,o){a(i).closest("li").removeClass("ui-state-default").addClass("ui-tabs-selected ui-state-active");o.removeClass("ui-tabs-hide");p._trigger("show",null,p._ui(i,o[0]))};var l=b?function(o,i){i.animate(b,b.duration||"normal",function(){p.lis.removeClass("ui-tabs-selected ui-state-active").addClass("ui-state-default");i.addClass("ui-tabs-hide");e(i,b);p.element.dequeue("tabs")})}:function(o,i,q){p.lis.removeClass("ui-tabs-selected ui-state-active").addClass("ui-state-default");i.addClass("ui-tabs-hide");p.element.dequeue("tabs")};this.anchors.bind(d.event+".tabs",function(){var o=this,r=a(this).closest("li"),i=p.panels.filter(":not(.ui-tabs-hide)"),q=a(p._sanitizeSelector(this.hash));if((r.hasClass("ui-tabs-selected")&&!d.collapsible)||r.hasClass("ui-state-disabled")||r.hasClass("ui-state-processing")||p._trigger("select",null,p._ui(this,q[0]))===false){this.blur();return false}d.selected=p.anchors.index(this);p.abort();if(d.collapsible){if(r.hasClass("ui-tabs-selected")){d.selected=-1;if(d.cookie){p._cookie(d.selected,d.cookie)}p.element.queue("tabs",function(){l(o,i)}).dequeue("tabs");this.blur();return false}else{if(!i.length){if(d.cookie){p._cookie(d.selected,d.cookie)}p.element.queue("tabs",function(){k(o,q)});p.load(p.anchors.index(this));this.blur();return false}}}if(d.cookie){p._cookie(d.selected,d.cookie)}if(q.length){if(i.length){p.element.queue("tabs",function(){l(o,i)})}p.element.queue("tabs",function(){k(o,q)});p.load(p.anchors.index(this))}else{throw"jQuery UI Tabs: Mismatching fragment identifier."}if(a.browser.msie){this.blur()}});this.anchors.bind("click.tabs",function(){return false})},destroy:function(){var b=this.options;this.abort();this.element.unbind(".tabs").removeClass("ui-tabs ui-widget ui-widget-content ui-corner-all ui-tabs-collapsible").removeData("tabs");this.list.removeClass("ui-tabs-nav ui-helper-reset ui-helper-clearfix ui-widget-header ui-corner-all");this.anchors.each(function(){var c=a.data(this,"href.tabs");if(c){this.href=c}var d=a(this).unbind(".tabs");a.each(["href","load","cache"],function(e,f){d.removeData(f+".tabs")})});this.lis.unbind(".tabs").add(this.panels).each(function(){if(a.data(this,"destroy.tabs")){a(this).remove()}else{a(this).removeClass(["ui-state-default","ui-corner-top","ui-tabs-selected","ui-state-active","ui-state-hover","ui-state-focus","ui-state-disabled","ui-tabs-panel","ui-widget-content","ui-corner-bottom","ui-tabs-hide"].join(" "))}});if(b.cookie){this._cookie(null,b.cookie)}},add:function(e,d,c){if(c===undefined){c=this.anchors.length}var b=this,g=this.options,i=a(g.tabTemplate.replace(/#\{href\}/g,e).replace(/#\{label\}/g,d)),h=!e.indexOf("#")?e.replace("#",""):this._tabId(a("a",i)[0]);i.addClass("ui-state-default ui-corner-top").data("destroy.tabs",true);var f=a("#"+h);if(!f.length){f=a(g.panelTemplate).attr("id",h).data("destroy.tabs",true)}f.addClass("ui-tabs-panel ui-widget-content ui-corner-bottom ui-tabs-hide");if(c>=this.lis.length){i.appendTo(this.list);f.appendTo(this.list[0].parentNode)}else{i.insertBefore(this.lis[c]);f.insertBefore(this.panels[c])}g.disabled=a.map(g.disabled,function(k,j){return k>=c?++k:k});this._tabify();if(this.anchors.length==1){i.addClass("ui-tabs-selected ui-state-active");f.removeClass("ui-tabs-hide");this.element.queue("tabs",function(){b._trigger("show",null,b._ui(b.anchors[0],b.panels[0]))});this.load(0)}this._trigger("add",null,this._ui(this.anchors[c],this.panels[c]))},remove:function(b){var d=this.options,e=this.lis.eq(b).remove(),c=this.panels.eq(b).remove();if(e.hasClass("ui-tabs-selected")&&this.anchors.length>1){this.select(b+(b+1=b?--g:g});this._tabify();this._trigger("remove",null,this._ui(e.find("a")[0],c[0]))},enable:function(b){var c=this.options;if(a.inArray(b,c.disabled)==-1){return}this.lis.eq(b).removeClass("ui-state-disabled");c.disabled=a.grep(c.disabled,function(e,d){return e!=b});this._trigger("enable",null,this._ui(this.anchors[b],this.panels[b]))},disable:function(c){var b=this,d=this.options;if(c!=d.selected){this.lis.eq(c).addClass("ui-state-disabled");d.disabled.push(c);d.disabled.sort();this._trigger("disable",null,this._ui(this.anchors[c],this.panels[c]))}},select:function(b){if(typeof b=="string"){b=this.anchors.index(this.anchors.filter("[href$="+b+"]"))}else{if(b===null){b=-1}}if(b==-1&&this.options.collapsible){b=this.options.selected}this.anchors.eq(b).trigger(this.options.event+".tabs")},load:function(e){var c=this,g=this.options,b=this.anchors.eq(e)[0],d=a.data(b,"load.tabs");this.abort();if(!d||this.element.queue("tabs").length!==0&&a.data(b,"cache.tabs")){this.element.dequeue("tabs");return}this.lis.eq(e).addClass("ui-state-processing");if(g.spinner){var f=a("span",b);f.data("label.tabs",f.html()).html(g.spinner)}this.xhr=a.ajax(a.extend({},g.ajaxOptions,{url:d,success:function(i,h){a(c._sanitizeSelector(b.hash)).html(i);c._cleanup();if(g.cache){a.data(b,"cache.tabs",true)}c._trigger("load",null,c._ui(c.anchors[e],c.panels[e]));try{g.ajaxOptions.success(i,h)}catch(j){}c.element.dequeue("tabs")}}))},abort:function(){this.element.queue([]);this.panels.stop(false,true);if(this.xhr){this.xhr.abort();delete this.xhr}this._cleanup()},url:function(c,b){this.anchors.eq(c).removeData("cache.tabs").data("load.tabs",b)},length:function(){return this.anchors.length}});a.extend(a.ui.tabs,{version:"1.7.1",getter:"length",defaults:{ajaxOptions:null,cache:false,cookie:null,collapsible:false,disabled:[],event:"click",fx:null,idPrefix:"ui-tabs-",panelTemplate:"
    ",spinner:"Loading…",tabTemplate:'
  • #{label}
  • '}});a.extend(a.ui.tabs.prototype,{rotation:null,rotate:function(d,f){var b=this,g=this.options;var c=b._rotate||(b._rotate=function(h){clearTimeout(b.rotation);b.rotation=setTimeout(function(){var i=g.selected;b.select(++i 0) { - history_pointer--; - $('#wc-command').val(commands_history[history_pointer]); - } - break; - case 40: // this is the arrow down - if (history_pointer < commands_history.length - 1 ) { - history_pointer++; - $('#wc-command').val(commands_history[history_pointer]); - } - break; - default: - break; - } - } - - var commands_history = new Array(); - var history_pointer; diff --git a/bundles/admin/src/main/resources/struts.xml b/bundles/admin/src/main/resources/struts.xml deleted file mode 100644 index a6e545e5f3..0000000000 --- a/bundles/admin/src/main/resources/struts.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - - - - - - - - {1} - viewBundle.ftl - - - - viewBundles.ftl - - - - - commandResult.ftl - - - - shell.ftl - - - diff --git a/bundles/demo/pom.xml b/bundles/demo/pom.xml deleted file mode 100644 index 0344df53c9..0000000000 --- a/bundles/demo/pom.xml +++ /dev/null @@ -1,65 +0,0 @@ - - - 4.0.0 - - org.apache.struts - struts2-osgi-bundles - 2.5.11-SNAPSHOT - - - struts2-osgi-demo-bundle - bundle - Struts 2 OSGi Demo Bundle - - - - - org.apache.velocity - velocity - - - - org.apache.velocity - velocity-tools - true - - - - commons-digester - commons-digester - - - - org.apache.struts - struts2-convention-plugin - - - - org.apache.struts - struts2-osgi-plugin - - - - - - - - org.apache.felix - maven-bundle-plugin - true - 2.1.0 - - - META-INF - *,com.opensymphony.xwork2 - *;create-asynchronously:=false - true - - - - - - - UTF-8 - - diff --git a/bundles/demo/src/main/java/actions/osgi/BundlesAction.java b/bundles/demo/src/main/java/actions/osgi/BundlesAction.java deleted file mode 100644 index eff79cccea..0000000000 --- a/bundles/demo/src/main/java/actions/osgi/BundlesAction.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * $Id$ - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package actions.osgi; - -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.convention.annotation.ResultPath; -import org.apache.struts2.osgi.interceptor.BundleContextAware; -import org.osgi.framework.Bundle; -import org.osgi.framework.BundleContext; - -/** - * This action shows how to interact with the OSGi container, using the OSGi interceptor - */ -@ResultPath("/content") -public class BundlesAction extends ActionSupport implements BundleContextAware { - private BundleContext bundleContext; - - public void setBundleContext(BundleContext bundleContext) { - this.bundleContext = bundleContext; - } - - public Bundle[] getBundles() { - return bundleContext.getBundles(); - } -} diff --git a/bundles/demo/src/main/java/actions/osgi/HelloWorldAction.java b/bundles/demo/src/main/java/actions/osgi/HelloWorldAction.java deleted file mode 100644 index cfaa2797a2..0000000000 --- a/bundles/demo/src/main/java/actions/osgi/HelloWorldAction.java +++ /dev/null @@ -1,34 +0,0 @@ -package actions.osgi; - -import com.opensymphony.xwork2.ActionSupport; -import org.apache.struts2.convention.annotation.Action; -import org.apache.struts2.convention.annotation.ResultPath; - -@ResultPath("/content") -public class HelloWorldAction extends ActionSupport { - private Message message; - - @Action("hello-convention") - public String execute() { - return SUCCESS; - } - - public Message getMessage() { - return message; - } - - public void setMessage(Message message) { - this.message = message; - } - - public String getSimpleMessage() { - return "Hello!!!"; - } - - public String toString() { - StringBuilder sb = new StringBuilder("{message:"); - sb.append(message != null ? message.getText() : "null"); - sb.append("}"); - return sb.toString(); - } -} \ No newline at end of file diff --git a/bundles/demo/src/main/java/actions/osgi/Message.java b/bundles/demo/src/main/java/actions/osgi/Message.java deleted file mode 100644 index eb31f29489..0000000000 --- a/bundles/demo/src/main/java/actions/osgi/Message.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * $Id$ - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package actions.osgi; - -public class Message { - private String text; - - public Message(String text) { - this.text = text; - } - - public String getText() { - return text; - } - - public void setText(String text) { - this.text = text; - } -} diff --git a/bundles/demo/src/main/resources/META-INF/spring/applicationContext.xml b/bundles/demo/src/main/resources/META-INF/spring/applicationContext.xml deleted file mode 100644 index aae9d2b422..0000000000 --- a/bundles/demo/src/main/resources/META-INF/spring/applicationContext.xml +++ /dev/null @@ -1,13 +0,0 @@ - - - - - - - - - - - - diff --git a/bundles/demo/src/main/resources/content/osgi/bundles.ftl b/bundles/demo/src/main/resources/content/osgi/bundles.ftl deleted file mode 100644 index e9decadf04..0000000000 --- a/bundles/demo/src/main/resources/content/osgi/bundles.ftl +++ /dev/null @@ -1,18 +0,0 @@ - - - OSGi integration - - - This action was mapped by Convention, and shows how to get access to the BundleContext - and registered services -
    - Spring Application Contexts: ${applicationContextsCount!} -
    - Bundles List: -
      - <#list bundles as bundle> -
    • ${bundle.symbolicName!}
    • - -
    - - \ No newline at end of file diff --git a/bundles/demo/src/main/resources/content/osgi/hello-convention.ftl b/bundles/demo/src/main/resources/content/osgi/hello-convention.ftl deleted file mode 100644 index e47d160cea..0000000000 --- a/bundles/demo/src/main/resources/content/osgi/hello-convention.ftl +++ /dev/null @@ -1,10 +0,0 @@ - - - Action mapped by the Convention plugin - - - This is an action mapped by the Convention plugin, using a FreeMarker result. -
    - Message from Action: ${simpleMessage} - - \ No newline at end of file diff --git a/bundles/demo/src/main/resources/content/osgi/hello.ftl b/bundles/demo/src/main/resources/content/osgi/hello.ftl deleted file mode 100644 index fec234335b..0000000000 --- a/bundles/demo/src/main/resources/content/osgi/hello.ftl +++ /dev/null @@ -1,10 +0,0 @@ - - - Action mapped by the XML configurationn - - - This is an action mapped by XML configuration, using a FreeMarker result. -
    - Message from Action: ${message.text} - - \ No newline at end of file diff --git a/bundles/demo/src/main/resources/content/osgi/hello.vm b/bundles/demo/src/main/resources/content/osgi/hello.vm deleted file mode 100644 index 40c1ff0298..0000000000 --- a/bundles/demo/src/main/resources/content/osgi/hello.vm +++ /dev/null @@ -1,10 +0,0 @@ - - - Action mapped by the XML configurationn - - - This is an action mapped by XML configuration, using a Velocity result. -
    - Message from Action: $message.text - - \ No newline at end of file diff --git a/bundles/demo/src/main/resources/content/osgi/home.ftl b/bundles/demo/src/main/resources/content/osgi/home.ftl deleted file mode 100644 index 089c89e85a..0000000000 --- a/bundles/demo/src/main/resources/content/osgi/home.ftl +++ /dev/null @@ -1,14 +0,0 @@ - - - OSGi Demo Bundle - - - This demo contains actions that will be packaged into an OSGi bundle and loaded by the Struts 2 OSGi plugin. -
    -
      -
    • <@s.a namespace="/osgi" action="hello-convention">Action mapped by the Convention plugin, with FreeMarker result
    • -
    • <@s.a namespace="/osgi" action="hello-freemarker">Action mapped by XML, with FreeMarker result
    • -
    • <@s.a namespace="/osgi" action="hello-velocity">Action mapped by XML, with Velocity result
    • -
    - - \ No newline at end of file diff --git a/bundles/demo/src/main/resources/struts.xml b/bundles/demo/src/main/resources/struts.xml deleted file mode 100644 index 3f72ce8619..0000000000 --- a/bundles/demo/src/main/resources/struts.xml +++ /dev/null @@ -1,20 +0,0 @@ - - - - - - - - /content/osgi/hello.vm - - - /content/osgi/hello.ftl - - - - /content/osgi/home.ftl - - - \ No newline at end of file diff --git a/bundles/pom.xml b/bundles/pom.xml deleted file mode 100755 index 4efe74945b..0000000000 --- a/bundles/pom.xml +++ /dev/null @@ -1,88 +0,0 @@ - - - - 4.0.0 - - org.apache.struts - struts2-parent - 2.5.11-SNAPSHOT - - - struts2-osgi-bundles - pom - Struts OSGi Bundles - - - admin - demo - - - - - - org.apache.struts - struts2-core - - - - - junit - junit - compile - - - - - javax.servlet - servlet-api - 2.4 - provided - - - - - - - - - org.codehaus.mojo - rat-maven-plugin - 1.0-alpha-2 - - - pom.xml - src/** - - - src/main/resources/*LICENSE.txt - - - - - - - - UTF-8 - - diff --git a/core/README.md b/core/README.md new file mode 100644 index 0000000000..0d10dcbc9d --- /dev/null +++ b/core/README.md @@ -0,0 +1,6 @@ +# Struts 2 Core +This is a core of the Apache Struts framework and all other modules depend on it. +It requires Java 8 at minimum and a Servlet container supporting Java Servlet API 3.1 at least. + +## Installation +Just drop this plugin into `WEB-INF/lib` folder or add it as Maven dependency diff --git a/core/pom.xml b/core/pom.xml index fb71aa27ea..a70b30133c 100644 --- a/core/pom.xml +++ b/core/pom.xml @@ -1,8 +1,6 @@ - - org.apache.velocity - velocity - true + jakarta.servlet.jsp + jakarta.servlet.jsp-api + provided - org.apache.velocity - velocity-tools - true + ognl + ognl org.apache.logging.log4j log4j-api - ${log4j2.version} - commons-fileupload - commons-fileupload + org.apache.commons + commons-fileupload2-jakarta-servlet6 commons-io commons-io - - commons-logging - commons-logging - true + org.apache.commons + commons-lang3 org.apache.commons - commons-lang3 + commons-text + - org.springframework - spring-core + + org.hibernate + hibernate-core + 5.6.15.Final true + org.springframework spring-aop true + org.springframework - spring-aspects - true + spring-test + test org.springframework - spring-beans - true + spring-web + test org.springframework spring-context - true + test org.springframework spring-context-support - true - - - org.springframework - spring-web - true + test - org.springframework - spring-test + jakarta.el + jakarta.el-api test - cglib - cglib-nodep - true + org.awaitility + awaitility + test junit junit + compile true org.apache.logging.log4j log4j-core - ${log4j2.version} test @@ -334,26 +254,7 @@ mockobjects - mockobjects-jdk1.3 - test - - - - mockobjects - mockobjects-alt-jdk1.3 - test - - - - mockobjects - mockobjects-alt-jdk1.3-j2ee1.3 - test - - - - mockobjects - mockobjects-jdk1.3-j2ee1.3 - test + mockobjects-core @@ -364,21 +265,16 @@ org.mockito - mockito-all + mockito-core test - org.easytesting - fest-assert + org.assertj + assertj-core test - - mockobjects - mockobjects-core - test - org.easymock easymock @@ -399,8 +295,7 @@ org.testng testng - compile - true + test @@ -412,15 +307,6 @@ org.slf4j slf4j-simple - true - - - - - javax.servlet - javax.servlet-api - 3.1.0 test diff --git a/core/src/main/java/com/opensymphony/xwork2/Action.java b/core/src/main/java/com/opensymphony/xwork2/Action.java deleted file mode 100644 index c9274c5785..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/Action.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -/** - * All actions may implement this interface, which exposes the execute() method. - *

    - * However, as of XWork 1.1, this is not required and is only here to assist users. You are free to create POJOs - * that honor the same contract defined by this interface without actually implementing the interface. - *

    - */ -public interface Action { - - /** - * The action execution was successful. Show result - * view to the end user. - */ - public static final String SUCCESS = "success"; - - /** - * The action execution was successful but do not - * show a view. This is useful for actions that are - * handling the view in another fashion like redirect. - */ - public static final String NONE = "none"; - - /** - * The action execution was a failure. - * Show an error view, possibly asking the - * user to retry entering data. - */ - public static final String ERROR = "error"; - - /** - *

    - * The action execution require more input - * in order to succeed. - * This result is typically used if a form - * handling action has been executed so as - * to provide defaults for a form. The - * form associated with the handler should be - * shown to the end user. - *

    - * - *

    - * This result is also used if the given input - * params are invalid, meaning the user - * should try providing input again. - *

    - */ - public static final String INPUT = "input"; - - /** - * The action could not execute, since the - * user most was not logged in. The login view - * should be shown. - */ - public static final String LOGIN = "login"; - - - /** - * Where the logic of the action is executed. - * - * @return a string representing the logical result of the execution. - * See constants in this interface for a list of standard result values. - * @throws Exception thrown if a system level exception occurs. - * Note: Application level exceptions should be handled by returning - * an error value, such as Action.ERROR. - */ - public String execute() throws Exception; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java b/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java deleted file mode 100644 index 5ec151326e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ActionChainResult.java +++ /dev/null @@ -1,290 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.TextParseUtil; -import com.opensymphony.xwork2.util.ValueStack; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.*; - - -/** -* -* -* This result invokes an entire other action, complete with it's own interceptor stack and result. -* -* -* -* This result type takes the following parameters: -* -* -* -*
      -* -*
    • actionName (default) - the name of the action that will be chained to
    • -* -*
    • namespace - used to determine which namespace the Action is in that we're chaining. If namespace is null, -* this defaults to the current namespace
    • -* -*
    • method - used to specify another method on target action to be invoked. -* If null, this defaults to execute method
    • -* -*
    • skipActions - (optional) the list of comma separated action names for the -* actions that could be chained to
    • -* -*
    -* -* -* -* Example: -* -*
    
    -* <package name="public" extends="struts-default">
    -*     <!-- Chain creatAccount to login, using the default parameter -->
    -*     <action name="createAccount" class="...">
    -*         <result type="chain">login</result>
    -*     </action>
    -*
    -*     <action name="login" class="...">
    -*         <!-- Chain to another namespace -->
    -*         <result type="chain">
    -*             <param name="actionName">dashboard</param>
    -*             <param name="namespace">/secure</param>
    -*         </result>
    -*     </action>
    -* </package>
    -*
    -* <package name="secure" extends="struts-default" namespace="/secure">
    -*     <action name="dashboard" class="...">
    -*         <result>dashboard.jsp</result>
    -*     </action>
    -* </package>
    -* 
    -* -* @author Alexandru Popescu -*/ -public class ActionChainResult implements Result { - - private static final Logger LOG = LogManager.getLogger(ActionChainResult.class); - - /** - * The result parameter name to set the name of the action to chain to. - */ - public static final String DEFAULT_PARAM = "actionName"; - - /** - * The action context key to save the chain history. - */ - private static final String CHAIN_HISTORY = "CHAIN_HISTORY"; - - /** - * The result parameter name to set the name of the action to chain to. - */ - public static final String SKIP_ACTIONS_PARAM = "skipActions"; - - - private ActionProxy proxy; - private String actionName; - - private String namespace; - - private String methodName; - - /** - * The list of actions to skip. - */ - private String skipActions; - - private ActionProxyFactory actionProxyFactory; - - public ActionChainResult() { - super(); - } - - public ActionChainResult(String namespace, String actionName, String methodName) { - this.namespace = namespace; - this.actionName = actionName; - this.methodName = methodName; - } - - public ActionChainResult(String namespace, String actionName, String methodName, String skipActions) { - this.namespace = namespace; - this.actionName = actionName; - this.methodName = methodName; - this.skipActions = skipActions; - } - - - /** - * @param actionProxyFactory the actionProxyFactory to set - */ - @Inject - public void setActionProxyFactory(ActionProxyFactory actionProxyFactory) { - this.actionProxyFactory = actionProxyFactory; - } - - /** - * Set the action name. - * - * @param actionName The action name. - */ - public void setActionName(String actionName) { - this.actionName = actionName; - } - - /** - * sets the namespace of the Action that we're chaining to. if namespace - * is null, this defaults to the current namespace. - * - * @param namespace the name of the namespace we're chaining to - */ - public void setNamespace(String namespace) { - this.namespace = namespace; - } - - /** - * Set the list of actions to skip. - * To test if an action should not throe an infinite recursion, - * only the action name is used, not the namespace. - * - * @param actions The list of action name separated by a white space. - */ - public void setSkipActions(String actions) { - this.skipActions = actions; - } - - - public void setMethod(String method) { - this.methodName = method; - } - - public ActionProxy getProxy() { - return proxy; - } - - /** - * Get the XWork chain history. - * The stack is a list of namespace/action!method keys. - * - * @return the chain history as string list - */ - public static LinkedList getChainHistory() { - LinkedList chainHistory = (LinkedList) ActionContext.getContext().get(CHAIN_HISTORY); - // Add if not exists - if (chainHistory == null) { - chainHistory = new LinkedList<>(); - ActionContext.getContext().put(CHAIN_HISTORY, chainHistory); - } - - return chainHistory; - } - - /** - * @param invocation the DefaultActionInvocation calling the action call stack - */ - public void execute(ActionInvocation invocation) throws Exception { - // if the finalNamespace wasn't explicitly defined, assume the current one - if (this.namespace == null) { - this.namespace = invocation.getProxy().getNamespace(); - } - - ValueStack stack = ActionContext.getContext().getValueStack(); - String finalNamespace = TextParseUtil.translateVariables(namespace, stack); - String finalActionName = TextParseUtil.translateVariables(actionName, stack); - String finalMethodName = this.methodName != null - ? TextParseUtil.translateVariables(this.methodName, stack) - : null; - - if (isInChainHistory(finalNamespace, finalActionName, finalMethodName)) { - addToHistory(finalNamespace, finalActionName, finalMethodName); - throw new XWorkException("Infinite recursion detected: " + ActionChainResult.getChainHistory().toString()); - } - - if (ActionChainResult.getChainHistory().isEmpty() && invocation != null && invocation.getProxy() != null) { - addToHistory(finalNamespace, invocation.getProxy().getActionName(), invocation.getProxy().getMethod()); - } - addToHistory(finalNamespace, finalActionName, finalMethodName); - - HashMap extraContext = new HashMap<>(); - extraContext.put(ActionContext.VALUE_STACK, ActionContext.getContext().getValueStack()); - extraContext.put(ActionContext.PARAMETERS, ActionContext.getContext().getParameters()); - extraContext.put(CHAIN_HISTORY, ActionChainResult.getChainHistory()); - - LOG.debug("Chaining to action {}", finalActionName); - - proxy = actionProxyFactory.createActionProxy(finalNamespace, finalActionName, finalMethodName, extraContext); - proxy.execute(); - } - - @Override public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final ActionChainResult that = (ActionChainResult) o; - - if (actionName != null ? !actionName.equals(that.actionName) : that.actionName != null) return false; - if (methodName != null ? !methodName.equals(that.methodName) : that.methodName != null) return false; - if (namespace != null ? !namespace.equals(that.namespace) : that.namespace != null) return false; - - return true; - } - - @Override public int hashCode() { - int result; - result = (actionName != null ? actionName.hashCode() : 0); - result = 31 * result + (namespace != null ? namespace.hashCode() : 0); - result = 31 * result + (methodName != null ? methodName.hashCode() : 0); - return result; - } - - private boolean isInChainHistory(String namespace, String actionName, String methodName) { - LinkedList chainHistory = ActionChainResult.getChainHistory(); - - if (chainHistory == null) { - return false; - } else { - // Actions to skip - Set skipActionsList = new HashSet<>(); - if (skipActions != null && skipActions.length() > 0) { - ValueStack stack = ActionContext.getContext().getValueStack(); - String finalSkipActions = TextParseUtil.translateVariables(this.skipActions, stack); - skipActionsList.addAll(TextParseUtil.commaDelimitedStringToSet(finalSkipActions)); - } - if (!skipActionsList.contains(actionName)) { - // Get if key is in the chain history - return chainHistory.contains(makeKey(namespace, actionName, methodName)); - } - - return false; - } - } - - private void addToHistory(String namespace, String actionName, String methodName) { - List chainHistory = ActionChainResult.getChainHistory(); - chainHistory.add(makeKey(namespace, actionName, methodName)); - } - - private String makeKey(String namespace, String actionName, String methodName) { - if (null == methodName) { - return namespace + "/" + actionName; - } - - return namespace + "/" + actionName + "!" + methodName; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionContext.java b/core/src/main/java/com/opensymphony/xwork2/ActionContext.java deleted file mode 100644 index 3e5c6d6aee..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ActionContext.java +++ /dev/null @@ -1,360 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.util.ValueStack; -import org.apache.struts2.dispatcher.HttpParameters; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - - -/** - *

    - * The ActionContext is the context in which an {@link Action} is executed. Each context is basically a - * container of objects an action needs for execution like the session, parameters, locale, etc. - *

    - * - *

    - * The ActionContext is thread local which means that values stored in the ActionContext are - * unique per thread. See the {@link ThreadLocal} class for more information. The benefit of - * this is you don't need to worry about a user specific action context, you just get it: - *

    - * - * ActionContext context = ActionContext.getContext(); - * - *

    - * Finally, because of the thread local usage you don't need to worry about making your actions thread safe. - *

    - * - * @author Patrick Lightbody - * @author Bill Lynch (docs) - */ -public class ActionContext implements Serializable { - - static ThreadLocal actionContext = new ThreadLocal<>(); - - /** - * Constant for the name of the action being executed. - */ - public static final String ACTION_NAME = "com.opensymphony.xwork2.ActionContext.name"; - - /** - * Constant for the {@link com.opensymphony.xwork2.util.ValueStack OGNL value stack}. - */ - public static final String VALUE_STACK = ValueStack.VALUE_STACK; - - /** - * Constant for the action's session. - */ - public static final String SESSION = "com.opensymphony.xwork2.ActionContext.session"; - - /** - * Constant for the action's application context. - */ - public static final String APPLICATION = "com.opensymphony.xwork2.ActionContext.application"; - - /** - * Constant for the action's parameters. - */ - public static final String PARAMETERS = "com.opensymphony.xwork2.ActionContext.parameters"; - - /** - * Constant for the action's locale. - */ - public static final String LOCALE = "com.opensymphony.xwork2.ActionContext.locale"; - - /** - * Constant for the action's type converter. - */ - public static final String TYPE_CONVERTER = "com.opensymphony.xwork2.ActionContext.typeConverter"; - - /** - * Constant for the action's {@link com.opensymphony.xwork2.ActionInvocation invocation} context. - */ - public static final String ACTION_INVOCATION = "com.opensymphony.xwork2.ActionContext.actionInvocation"; - - /** - * Constant for the map of type conversion errors. - */ - public static final String CONVERSION_ERRORS = "com.opensymphony.xwork2.ActionContext.conversionErrors"; - - - /** - * Constant for the container - */ - public static final String CONTAINER = "com.opensymphony.xwork2.ActionContext.container"; - - private Map context; - - /** - * Creates a new ActionContext initialized with another context. - * - * @param context a context map. - */ - public ActionContext(Map context) { - this.context = context; - } - - - /** - * Sets the action invocation (the execution state). - * - * @param actionInvocation the action execution state. - */ - public void setActionInvocation(ActionInvocation actionInvocation) { - put(ACTION_INVOCATION, actionInvocation); - } - - /** - * Gets the action invocation (the execution state). - * - * @return the action invocation (the execution state). - */ - public ActionInvocation getActionInvocation() { - return (ActionInvocation) get(ACTION_INVOCATION); - } - - /** - * Sets the action's application context. - * - * @param application the action's application context. - */ - public void setApplication(Map application) { - put(APPLICATION, application); - } - - /** - * Returns a Map of the ServletContext when in a servlet environment or a generic application level Map otherwise. - * - * @return a Map of ServletContext or generic application level Map - */ - public Map getApplication() { - return (Map) get(APPLICATION); - } - - /** - * Sets the action context for the current thread. - * - * @param context the action context. - */ - public static void setContext(ActionContext context) { - actionContext.set(context); - } - - /** - * Returns the ActionContext specific to the current thread. - * - * @return the ActionContext for the current thread, is never null. - */ - public static ActionContext getContext() { - return actionContext.get(); - } - - /** - * Sets the action's context map. - * - * @param contextMap the context map. - */ - public void setContextMap(Map contextMap) { - getContext().context = contextMap; - } - - /** - * Gets the context map. - * - * @return the context map. - */ - public Map getContextMap() { - return context; - } - - /** - * Sets conversion errors which occurred when executing the action. - * - * @param conversionErrors a Map of errors which occurred when executing the action. - */ - public void setConversionErrors(Map conversionErrors) { - put(CONVERSION_ERRORS, conversionErrors); - } - - /** - * Gets the map of conversion errors which occurred when executing the action. - * - * @return the map of conversion errors which occurred when executing the action or an empty map if - * there were no errors. - */ - public Map getConversionErrors() { - Map errors = (Map) get(CONVERSION_ERRORS); - - if (errors == null) { - errors = new HashMap<>(); - setConversionErrors(errors); - } - - return errors; - } - - /** - * Sets the Locale for the current action. - * - * @param locale the Locale for the current action. - */ - public void setLocale(Locale locale) { - put(LOCALE, locale); - } - - /** - * Gets the Locale of the current action. If no locale was ever specified the platform's - * {@link java.util.Locale#getDefault() default locale} is used. - * - * @return the Locale of the current action. - */ - public Locale getLocale() { - Locale locale = (Locale) get(LOCALE); - - if (locale == null) { - locale = Locale.getDefault(); - setLocale(locale); - } - - return locale; - } - - /** - * Sets the name of the current Action in the ActionContext. - * - * @param name the name of the current action. - */ - public void setName(String name) { - put(ACTION_NAME, name); - } - - /** - * Gets the name of the current Action. - * - * @return the name of the current action. - */ - public String getName() { - return (String) get(ACTION_NAME); - } - - /** - * Sets the action parameters. - * - * @param parameters the parameters for the current action. - */ - public void setParameters(HttpParameters parameters) { - put(PARAMETERS, parameters); - } - - /** - * Returns a Map of the HttpServletRequest parameters when in a servlet environment or a generic Map of - * parameters otherwise. - * - * @return a Map of HttpServletRequest parameters or a multipart map when in a servlet environment, or a - * generic Map of parameters otherwise. - */ - public HttpParameters getParameters() { - return (HttpParameters) get(PARAMETERS); - } - - /** - * Sets a map of action session values. - * - * @param session the session values. - */ - public void setSession(Map session) { - put(SESSION, session); - } - - /** - * Gets the Map of HttpSession values when in a servlet environment or a generic session map otherwise. - * - * @return the Map of HttpSession values when in a servlet environment or a generic session map otherwise. - */ - public Map getSession() { - return (Map) get(SESSION); - } - - /** - * Sets the OGNL value stack. - * - * @param stack the OGNL value stack. - */ - public void setValueStack(ValueStack stack) { - put(VALUE_STACK, stack); - } - - /** - * Gets the OGNL value stack. - * - * @return the OGNL value stack. - */ - public ValueStack getValueStack() { - return (ValueStack) get(VALUE_STACK); - } - - /** - * Gets the container for this request - * - * @param cont The container - */ - public void setContainer(Container cont) { - put(CONTAINER, cont); - } - - /** - * Sets the container for this request - * - * @return The container - */ - public Container getContainer() { - return (Container) get(CONTAINER); - } - - public T getInstance(Class type) { - Container cont = getContainer(); - if (cont != null) { - return cont.getInstance(type); - } else { - throw new XWorkException("Cannot find an initialized container for this request."); - } - } - - /** - * Returns a value that is stored in the current ActionContext by doing a lookup using the value's key. - * - * @param key the key used to find the value. - * @return the value that was found using the key or null if the key was not found. - */ - public Object get(String key) { - return context.get(key); - } - - /** - * Stores a value in the current ActionContext. The value can be looked up using the key. - * - * @param key the key of the value. - * @param value the value to be stored. - */ - public void put(String key, Object value) { - context.put(key, value); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionEventListener.java b/core/src/main/java/com/opensymphony/xwork2/ActionEventListener.java deleted file mode 100644 index 58c992a518..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ActionEventListener.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.util.ValueStack; - -/** - * Provides hooks for handling key action events - */ -public interface ActionEventListener { - /** - * Called after an action has been created. - * - * @param action The action - * @param stack The current value stack - * @return The action to use - */ - public Object prepare(Object action, ValueStack stack); - - /** - * Called when an exception is thrown by the action - * - * @param t The exception/error that was thrown - * @param stack The current value stack - * @return A result code to execute, can be null - */ - public String handleException(Throwable t, ValueStack stack); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionProxy.java b/core/src/main/java/com/opensymphony/xwork2/ActionProxy.java deleted file mode 100644 index 6064d26918..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ActionProxy.java +++ /dev/null @@ -1,105 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.config.entities.ActionConfig; - - -/** - * ActionProxy is an extra layer between XWork and the action so that different proxies are possible. - * - *

    - * An example of this would be a remote proxy, where the layer between XWork and the action might be RMI or SOAP. - *

    - * - * @author Jason Carreira - */ -public interface ActionProxy { - - /** - * Gets the Action instance for this Proxy. - * - * @return the Action instance - */ - Object getAction(); - - /** - * Gets the alias name this ActionProxy is mapped to. - * - * @return the alias name - */ - String getActionName(); - - /** - * Gets the ActionConfig this ActionProxy is built from. - * - * @return the ActionConfig - */ - ActionConfig getConfig(); - - /** - * Sets whether this ActionProxy should also execute the Result after executing the Action. - * - * @param executeResult true to also execute the Result. - */ - void setExecuteResult(boolean executeResult); - - /** - * Gets the status of whether the ActionProxy is set to execute the Result after the Action is executed. - * - * @return the status - */ - boolean getExecuteResult(); - - /** - * Gets the ActionInvocation associated with this ActionProxy. - * - * @return the ActionInvocation - */ - ActionInvocation getInvocation(); - - /** - * Gets the namespace the ActionConfig for this ActionProxy is mapped to. - * - * @return the namespace - */ - String getNamespace(); - - /** - * Execute this ActionProxy. This will set the ActionContext from the ActionInvocation into the ActionContext - * ThreadLocal before invoking the ActionInvocation, then set the old ActionContext back into the ThreadLocal. - * - * @return the result code returned from executing the ActionInvocation - * @throws Exception can be thrown. - * @see ActionInvocation - */ - String execute() throws Exception; - - /** - * Gets the method name to execute, or null if no method has been specified (meaning execute will be invoked). - * - * @return the method to execute - */ - String getMethod(); - - /** - * Gets status of the method value's initialization. - * - * @return true if the method returned by getMethod() is not a default initializer value. - */ - boolean isMethodSpecified(); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java b/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java deleted file mode 100644 index 0434469dd9..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ActionSupport.java +++ /dev/null @@ -1,297 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.interceptor.ValidationAware; -import com.opensymphony.xwork2.util.ValueStack; - -import java.io.Serializable; -import java.util.*; - -/** - * Provides a default implementation for the most common actions. - * See the documentation for all the interfaces this class implements for more detailed information. - */ -public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable { - - private final ValidationAwareSupport validationAware = new ValidationAwareSupport(); - - private transient TextProvider textProvider; - private transient LocaleProvider localeProvider; - - protected Container container; - - public void setActionErrors(Collection errorMessages) { - validationAware.setActionErrors(errorMessages); - } - - public Collection getActionErrors() { - return validationAware.getActionErrors(); - } - - public void setActionMessages(Collection messages) { - validationAware.setActionMessages(messages); - } - - public Collection getActionMessages() { - return validationAware.getActionMessages(); - } - - public void setFieldErrors(Map> errorMap) { - validationAware.setFieldErrors(errorMap); - } - - public Map> getFieldErrors() { - return validationAware.getFieldErrors(); - } - - @Override - public Locale getLocale() { - return getLocaleProvider().getLocale(); - } - - @Override - public boolean isValidLocaleString(String localeStr) { - return getLocaleProvider().isValidLocaleString(localeStr); - } - - @Override - public boolean isValidLocale(Locale locale) { - return getLocaleProvider().isValidLocale(locale); - } - - public boolean hasKey(String key) { - return getTextProvider().hasKey(key); - } - - public String getText(String aTextName) { - return getTextProvider().getText(aTextName); - } - - public String getText(String aTextName, String defaultValue) { - return getTextProvider().getText(aTextName, defaultValue); - } - - public String getText(String aTextName, String defaultValue, String obj) { - return getTextProvider().getText(aTextName, defaultValue, obj); - } - - public String getText(String aTextName, List args) { - return getTextProvider().getText(aTextName, args); - } - - public String getText(String key, String[] args) { - return getTextProvider().getText(key, args); - } - - public String getText(String aTextName, String defaultValue, List args) { - return getTextProvider().getText(aTextName, defaultValue, args); - } - - public String getText(String key, String defaultValue, String[] args) { - return getTextProvider().getText(key, defaultValue, args); - } - - public String getText(String key, String defaultValue, List args, ValueStack stack) { - return getTextProvider().getText(key, defaultValue, args, stack); - } - - public String getText(String key, String defaultValue, String[] args, ValueStack stack) { - return getTextProvider().getText(key, defaultValue, args, stack); - } - - /** - * Dedicated method to support I10N and conversion errors - * - * @param key message which contains formatting string - * @param expr that should be formatted - * @return formatted expr with format specified by key - */ - public String getFormatted(String key, String expr) { - Map conversionErrors = ActionContext.getContext().getConversionErrors(); - if (conversionErrors.containsKey(expr)) { - String[] vals = (String[]) conversionErrors.get(expr); - return vals[0]; - } else { - final ValueStack valueStack = ActionContext.getContext().getValueStack(); - final Object val = valueStack.findValue(expr); - return getText(key, Arrays.asList(val)); - } - } - - public ResourceBundle getTexts() { - return getTextProvider().getTexts(); - } - - public ResourceBundle getTexts(String aBundleName) { - return getTextProvider().getTexts(aBundleName); - } - - public void addActionError(String anErrorMessage) { - validationAware.addActionError(anErrorMessage); - } - - public void addActionMessage(String aMessage) { - validationAware.addActionMessage(aMessage); - } - - public void addFieldError(String fieldName, String errorMessage) { - validationAware.addFieldError(fieldName, errorMessage); - } - - public String input() throws Exception { - return INPUT; - } - - /** - * A default implementation that does nothing an returns "success". - * - *

    - * Subclasses should override this method to provide their business logic. - *

    - * - *

    - * See also {@link com.opensymphony.xwork2.Action#execute()}. - *

    - * - * @return returns {@link #SUCCESS} - * @throws Exception can be thrown by subclasses. - */ - public String execute() throws Exception { - return SUCCESS; - } - - public boolean hasActionErrors() { - return validationAware.hasActionErrors(); - } - - public boolean hasActionMessages() { - return validationAware.hasActionMessages(); - } - - public boolean hasErrors() { - return validationAware.hasErrors(); - } - - public boolean hasFieldErrors() { - return validationAware.hasFieldErrors(); - } - - /** - * Clears field errors. Useful for Continuations and other situations - * where you might want to clear parts of the state on the same action. - */ - public void clearFieldErrors() { - validationAware.clearFieldErrors(); - } - - /** - * Clears action errors. Useful for Continuations and other situations - * where you might want to clear parts of the state on the same action. - */ - public void clearActionErrors() { - validationAware.clearActionErrors(); - } - - /** - * Clears messages. Useful for Continuations and other situations - * where you might want to clear parts of the state on the same action. - */ - public void clearMessages() { - validationAware.clearMessages(); - } - - /** - * Clears all errors. Useful for Continuations and other situations - * where you might want to clear parts of the state on the same action. - */ - public void clearErrors() { - validationAware.clearErrors(); - } - - /** - * Clears all errors and messages. Useful for Continuations and other situations - * where you might want to clear parts of the state on the same action. - */ - public void clearErrorsAndMessages() { - validationAware.clearErrorsAndMessages(); - } - - /** - * A default implementation that validates nothing. - * Subclasses should override this method to provide validations. - */ - public void validate() { - } - - @Override - public Object clone() throws CloneNotSupportedException { - return super.clone(); - } - - /** - * - * Stops the action invocation immediately (by throwing a PauseException) and causes the action invocation to return - * the specified result, such as {@link #SUCCESS}, {@link #INPUT}, etc. - * - *

    - * The next time this action is invoked (and using the same continuation ID), the method will resume immediately - * after where this method was called, with the entire call stack in the execute method restored. - *

    - * - *

    - * Note: this method can only be called within the {@link #execute()} method. - *

    - * - * - * - * @param result the result to return - the same type of return value in the {@link #execute()} method. - */ - public void pause(String result) { - } - - /** - * If called first time it will create {@link com.opensymphony.xwork2.TextProviderFactory}, - * inject dependency (if {@link com.opensymphony.xwork2.inject.Container} is accesible) into in, - * then will create new {@link com.opensymphony.xwork2.TextProvider} and store it in a field - * for future references and at the returns reference to that field - * - * @return reference to field with TextProvider - */ - protected TextProvider getTextProvider() { - if (textProvider == null) { - TextProviderFactory tpf = container.inject(TextProviderFactory.class); - textProvider = tpf.createInstance(getClass()); - } - return textProvider; - } - - protected LocaleProvider getLocaleProvider() { - if (localeProvider == null) { - LocaleProviderFactory localeProviderFactory = container.getInstance(LocaleProviderFactory.class); - localeProvider = localeProviderFactory.createLocaleProvider(); - } - return localeProvider; - } - - @Inject - public void setContainer(Container container) { - this.container = container; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java b/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java deleted file mode 100644 index 754ae5ae44..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultActionInvocation.java +++ /dev/null @@ -1,524 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.config.entities.InterceptorMapping; -import com.opensymphony.xwork2.config.entities.ResultConfig; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.interceptor.Interceptor; -import com.opensymphony.xwork2.interceptor.PreResultListener; -import com.opensymphony.xwork2.interceptor.WithLazyParams; -import com.opensymphony.xwork2.ognl.OgnlUtil; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.util.ValueStackFactory; -import com.opensymphony.xwork2.util.profiling.UtilTimerStack; -import ognl.MethodFailedException; -import ognl.NoSuchPropertyException; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; -import java.util.Map; - - -/** - * The Default ActionInvocation implementation - * - * @author Rainer Hermanns - * @author tmjee - * @version $Date$ $Id$ - * @see com.opensymphony.xwork2.DefaultActionProxy - */ -public class DefaultActionInvocation implements ActionInvocation { - - private static final Logger LOG = LogManager.getLogger(DefaultActionInvocation.class); - - protected Object action; - protected ActionProxy proxy; - protected List preResultListeners; - protected Map extraContext; - protected ActionContext invocationContext; - protected Iterator interceptors; - protected ValueStack stack; - protected Result result; - protected Result explicitResult; - protected String resultCode; - protected boolean executed = false; - protected boolean pushAction = true; - protected ObjectFactory objectFactory; - protected ActionEventListener actionEventListener; - protected ValueStackFactory valueStackFactory; - protected Container container; - protected UnknownHandlerManager unknownHandlerManager; - protected OgnlUtil ognlUtil; - protected WithLazyParams.LazyParamInjector lazyParamInjector; - - public DefaultActionInvocation(final Map extraContext, final boolean pushAction) { - this.extraContext = extraContext; - this.pushAction = pushAction; - } - - @Inject - public void setUnknownHandlerManager(UnknownHandlerManager unknownHandlerManager) { - this.unknownHandlerManager = unknownHandlerManager; - } - - @Inject - public void setValueStackFactory(ValueStackFactory fac) { - this.valueStackFactory = fac; - } - - @Inject - public void setObjectFactory(ObjectFactory fac) { - this.objectFactory = fac; - } - - @Inject - public void setContainer(Container cont) { - this.container = cont; - } - - @Inject(required=false) - public void setActionEventListener(ActionEventListener listener) { - this.actionEventListener = listener; - } - - @Inject - public void setOgnlUtil(OgnlUtil ognlUtil) { - this.ognlUtil = ognlUtil; - } - - public Object getAction() { - return action; - } - - public boolean isExecuted() { - return executed; - } - - public ActionContext getInvocationContext() { - return invocationContext; - } - - public ActionProxy getProxy() { - return proxy; - } - - /** - * If the DefaultActionInvocation has been executed before and the Result is an instance of ActionChainResult, this method - * will walk down the chain of ActionChainResults until it finds a non-chain result, which will be returned. If the - * DefaultActionInvocation's result has not been executed before, the Result instance will be created and populated with - * the result params. - * - * @return a Result instance - * @throws Exception in case of any error - */ - public Result getResult() throws Exception { - Result returnResult = result; - - // If we've chained to other Actions, we need to find the last result - while (returnResult instanceof ActionChainResult) { - ActionProxy aProxy = ((ActionChainResult) returnResult).getProxy(); - - if (aProxy != null) { - Result proxyResult = aProxy.getInvocation().getResult(); - - if ((proxyResult != null) && (aProxy.getExecuteResult())) { - returnResult = proxyResult; - } else { - break; - } - } else { - break; - } - } - - return returnResult; - } - - public String getResultCode() { - return resultCode; - } - - public void setResultCode(String resultCode) { - if (isExecuted()) { - throw new IllegalStateException("Result has already been executed."); - } - this.resultCode = resultCode; - } - - - public ValueStack getStack() { - return stack; - } - - /** - * Register a com.opensymphony.xwork2.interceptor.PreResultListener to be notified after the Action is executed and before the - * Result is executed. The ActionInvocation implementation must guarantee that listeners will be called in the order - * in which they are registered. Listener registration and execution does not need to be thread-safe. - * - * @param listener to register - */ - public void addPreResultListener(PreResultListener listener) { - if (preResultListeners == null) { - preResultListeners = new ArrayList<>(1); - } - - preResultListeners.add(listener); - } - - public Result createResult() throws Exception { - LOG.trace("Creating result related to resultCode [{}]", resultCode); - - if (explicitResult != null) { - Result ret = explicitResult; - explicitResult = null; - - return ret; - } - ActionConfig config = proxy.getConfig(); - Map results = config.getResults(); - - ResultConfig resultConfig = null; - - try { - resultConfig = results.get(resultCode); - } catch (NullPointerException e) { - LOG.debug("Got NPE trying to read result configuration for resultCode [{}]", resultCode); - } - - if (resultConfig == null) { - // If no result is found for the given resultCode, try to get a wildcard '*' match. - resultConfig = results.get("*"); - } - - if (resultConfig != null) { - try { - return objectFactory.buildResult(resultConfig, invocationContext.getContextMap()); - } catch (Exception e) { - LOG.error("There was an exception while instantiating the result of type {}", resultConfig.getClassName(), e); - throw new XWorkException(e, resultConfig); - } - } else if (resultCode != null && !Action.NONE.equals(resultCode) && unknownHandlerManager.hasUnknownHandlers()) { - return unknownHandlerManager.handleUnknownResult(invocationContext, proxy.getActionName(), proxy.getConfig(), resultCode); - } - return null; - } - - /** - * @throws ConfigurationException If no result can be found with the returned code - */ - public String invoke() throws Exception { - String profileKey = "invoke: "; - try { - UtilTimerStack.push(profileKey); - - if (executed) { - throw new IllegalStateException("Action has already executed"); - } - - if (interceptors.hasNext()) { - final InterceptorMapping interceptorMapping = interceptors.next(); - String interceptorMsg = "interceptorMapping: " + interceptorMapping.getName(); - UtilTimerStack.push(interceptorMsg); - try { - Interceptor interceptor = interceptorMapping.getInterceptor(); - if (interceptor instanceof WithLazyParams) { - interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext); - } - resultCode = interceptor.intercept(DefaultActionInvocation.this); - } finally { - UtilTimerStack.pop(interceptorMsg); - } - } else { - resultCode = invokeActionOnly(); - } - - // this is needed because the result will be executed, then control will return to the Interceptor, which will - // return above and flow through again - if (!executed) { - if (preResultListeners != null) { - LOG.trace("Executing PreResultListeners for result [{}]", result); - - for (Object preResultListener : preResultListeners) { - PreResultListener listener = (PreResultListener) preResultListener; - - String _profileKey = "preResultListener: "; - try { - UtilTimerStack.push(_profileKey); - listener.beforeResult(this, resultCode); - } - finally { - UtilTimerStack.pop(_profileKey); - } - } - } - - // now execute the result, if we're supposed to - if (proxy.getExecuteResult()) { - executeResult(); - } - - executed = true; - } - - return resultCode; - } - finally { - UtilTimerStack.pop(profileKey); - } - } - - public String invokeActionOnly() throws Exception { - return invokeAction(getAction(), proxy.getConfig()); - } - - protected void createAction(Map contextMap) { - // load action - String timerKey = "actionCreate: " + proxy.getActionName(); - try { - UtilTimerStack.push(timerKey); - action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap); - } catch (InstantiationException e) { - throw new XWorkException("Unable to instantiate Action!", e, proxy.getConfig()); - } catch (IllegalAccessException e) { - throw new XWorkException("Illegal access to constructor, is it public?", e, proxy.getConfig()); - } catch (Exception e) { - String gripe; - - if (proxy == null) { - gripe = "Whoa! No ActionProxy instance found in current ActionInvocation. This is bad ... very bad"; - } else if (proxy.getConfig() == null) { - gripe = "Sheesh. Where'd that ActionProxy get to? I can't find it in the current ActionInvocation!?"; - } else if (proxy.getConfig().getClassName() == null) { - gripe = "No Action defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'"; - } else { - gripe = "Unable to instantiate Action, " + proxy.getConfig().getClassName() + ", defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'"; - } - - gripe += (((" -- " + e.getMessage()) != null) ? e.getMessage() : " [no message in exception]"); - throw new XWorkException(gripe, e, proxy.getConfig()); - } finally { - UtilTimerStack.pop(timerKey); - } - - if (actionEventListener != null) { - action = actionEventListener.prepare(action, stack); - } - } - - protected Map createContextMap() { - Map contextMap; - - if ((extraContext != null) && (extraContext.containsKey(ActionContext.VALUE_STACK))) { - // In case the ValueStack was passed in - stack = (ValueStack) extraContext.get(ActionContext.VALUE_STACK); - - if (stack == null) { - throw new IllegalStateException("There was a null Stack set into the extra params."); - } - - contextMap = stack.getContext(); - } else { - // create the value stack - // this also adds the ValueStack to its context - stack = valueStackFactory.createValueStack(); - - // create the action context - contextMap = stack.getContext(); - } - - // put extraContext in - if (extraContext != null) { - contextMap.putAll(extraContext); - } - - //put this DefaultActionInvocation into the context map - contextMap.put(ActionContext.ACTION_INVOCATION, this); - contextMap.put(ActionContext.CONTAINER, container); - - return contextMap; - } - - /** - * Uses getResult to get the final Result and executes it - * - * @throws ConfigurationException If not result can be found with the returned code - */ - private void executeResult() throws Exception { - result = createResult(); - - String timerKey = "executeResult: " + getResultCode(); - try { - UtilTimerStack.push(timerKey); - if (result != null) { - result.execute(this); - } else if (resultCode != null && !Action.NONE.equals(resultCode)) { - throw new ConfigurationException("No result defined for action " + getAction().getClass().getName() - + " and result " + getResultCode(), proxy.getConfig()); - } else { - if (LOG.isDebugEnabled()) { - LOG.debug("No result returned for action {} at {}", getAction().getClass().getName(), proxy.getConfig().getLocation()); - } - } - } finally { - UtilTimerStack.pop(timerKey); - } - } - - public void init(ActionProxy proxy) { - this.proxy = proxy; - Map contextMap = createContextMap(); - - // Setting this so that other classes, like object factories, can use the ActionProxy and other - // contextual information to operate - ActionContext actionContext = ActionContext.getContext(); - - if (actionContext != null) { - actionContext.setActionInvocation(this); - } - - createAction(contextMap); - - if (pushAction) { - stack.push(action); - contextMap.put("action", action); - } - - invocationContext = new ActionContext(contextMap); - invocationContext.setName(proxy.getActionName()); - - createInterceptors(proxy); - - prepareLazyParamInjector(invocationContext.getValueStack()); - } - - protected void prepareLazyParamInjector(ValueStack valueStack) { - lazyParamInjector = new WithLazyParams.LazyParamInjector(valueStack); - container.inject(lazyParamInjector); - } - - protected void createInterceptors(ActionProxy proxy) { - // Get a new List so we don't get problems with the iterator if someone changes the original list - List interceptorList = new ArrayList<>(proxy.getConfig().getInterceptors()); - interceptors = interceptorList.iterator(); - } - - protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception { - String methodName = proxy.getMethod(); - - LOG.debug("Executing action method = {}", methodName); - - String timerKey = "invokeAction: " + proxy.getActionName(); - try { - UtilTimerStack.push(timerKey); - - Object methodResult; - try { - methodResult = ognlUtil.callMethod(methodName + "()", getStack().getContext(), action); - } catch (MethodFailedException e) { - // if reason is missing method, try checking UnknownHandlers - if (e.getReason() instanceof NoSuchMethodException) { - if (unknownHandlerManager.hasUnknownHandlers()) { - try { - methodResult = unknownHandlerManager.handleUnknownMethod(action, methodName); - } catch (NoSuchMethodException ignore) { - // throw the original one - throw e; - } - } else { - // throw the original one - throw e; - } - // throw the original exception as UnknownHandlers weren't able to handle invocation as well - if (methodResult == null) { - throw e; - } - } else { - // exception isn't related to missing action method, throw it - throw e; - } - } - return saveResult(actionConfig, methodResult); - } catch (NoSuchPropertyException e) { - throw new IllegalArgumentException("The " + methodName + "() is not defined in action " + getAction().getClass() + ""); - } catch (MethodFailedException e) { - // We try to return the source exception. - Throwable t = e.getCause(); - - if (actionEventListener != null) { - String result = actionEventListener.handleException(t, getStack()); - if (result != null) { - return result; - } - } - if (t instanceof Exception) { - throw (Exception) t; - } else { - throw e; - } - } finally { - UtilTimerStack.pop(timerKey); - } - } - - /** - * Save the result to be used later. - * @param actionConfig current ActionConfig - * @param methodResult the result of the action. - * @return the result code to process. - */ - protected String saveResult(ActionConfig actionConfig, Object methodResult) { - if (methodResult instanceof Result) { - this.explicitResult = (Result) methodResult; - - // Wire the result automatically - container.inject(explicitResult); - return null; - } else { - return (String) methodResult; - } - } - - /** - * Version ready to be serialize - * - * @return instance without reference to {@link Container} - */ - public ActionInvocation serialize() { - DefaultActionInvocation that = this; - that.container = null; - return that; - } - - /** - * Restoring Container - * - * @param actionContext current {@link ActionContext} - * @return instance which can be used to invoke action - */ - public ActionInvocation deserialize(ActionContext actionContext) { - DefaultActionInvocation that = this; - that.container = actionContext.getContainer(); - return that; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxyFactory.java b/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxyFactory.java deleted file mode 100644 index cf0c552e75..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxyFactory.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; - -import java.util.Map; - - -/** - * Default factory for {@link com.opensymphony.xwork2.ActionProxyFactory}. - * - * @author Jason Carreira - */ -public class DefaultActionProxyFactory implements ActionProxyFactory { - - protected Container container; - - public DefaultActionProxyFactory() { - super(); - } - - @Inject - public void setContainer(Container container) { - this.container = container; - } - - public ActionProxy createActionProxy(String namespace, String actionName, Map extraContext) { - return createActionProxy(namespace, actionName, null, extraContext, true, true); - } - - public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map extraContext) { - return createActionProxy(namespace, actionName, methodName, extraContext, true, true); - } - - public ActionProxy createActionProxy(String namespace, String actionName, Map extraContext, boolean executeResult, boolean cleanupContext) { - return createActionProxy(namespace, actionName, null, extraContext, executeResult, cleanupContext); - } - - public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map extraContext, boolean executeResult, boolean cleanupContext) { - - ActionInvocation inv = createActionInvocation(extraContext, true); - container.inject(inv); - return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); - } - - protected ActionInvocation createActionInvocation(Map extraContext, boolean pushAction) { - return new DefaultActionInvocation(extraContext, pushAction); - } - - public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, boolean executeResult, boolean cleanupContext) { - - return createActionProxy(inv, namespace, actionName, null, executeResult, cleanupContext); - } - - public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) { - - DefaultActionProxy proxy = new DefaultActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); - container.inject(proxy); - proxy.prepare(); - return proxy; - } - - @Override - public String toString() { - return getClass().getSimpleName(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultLocaleProvider.java b/core/src/main/java/com/opensymphony/xwork2/DefaultLocaleProvider.java deleted file mode 100644 index 19c8f5dc2c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultLocaleProvider.java +++ /dev/null @@ -1,37 +0,0 @@ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.util.DefaultLocalizedTextProvider; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.Arrays; -import java.util.Locale; - -/** - * Default implementation of {@link LocaleProvider} - */ -public class DefaultLocaleProvider implements LocaleProvider { - - private final static Logger LOG = LogManager.getLogger(DefaultLocaleProvider.class); - - @Override - public Locale getLocale() { - ActionContext ctx = ActionContext.getContext(); - if (ctx != null) { - return ctx.getLocale(); - } else { - LOG.debug("Action context not initialized"); - return null; - } - } - - @Override - public boolean isValidLocaleString(String localeStr) { - return isValidLocale(DefaultLocalizedTextProvider.localeFromString(localeStr, getLocale())); - } - - @Override - public boolean isValidLocale(Locale locale) { - return locale != null && Arrays.asList(Locale.getAvailableLocales()).contains(locale); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultLocaleProviderFactory.java b/core/src/main/java/com/opensymphony/xwork2/DefaultLocaleProviderFactory.java deleted file mode 100644 index 7abb64f25c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultLocaleProviderFactory.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.opensymphony.xwork2; - -public class DefaultLocaleProviderFactory implements LocaleProviderFactory { - - @Override - public LocaleProvider createLocaleProvider() { - return new DefaultLocaleProvider(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultTextProvider.java b/core/src/main/java/com/opensymphony/xwork2/DefaultTextProvider.java deleted file mode 100644 index 51ed449abb..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultTextProvider.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.DefaultLocalizedTextProvider; -import com.opensymphony.xwork2.util.ValueStack; - -import java.io.Serializable; -import java.text.MessageFormat; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.List; -import java.util.ResourceBundle; - -/** - * DefaultTextProvider gets texts from only the default resource bundles associated with the - * LocalizedTextUtil. - * - * @author Jason Carreira jcarreira@gmail.com - * @author Rainer Hermanns - * @see DefaultLocalizedTextProvider#addDefaultResourceBundle(String) - */ -public class DefaultTextProvider implements TextProvider, Serializable, Unchainable { - - private static final Object[] EMPTY_ARGS = new Object[0]; - - protected LocalizedTextProvider localizedTextProvider; - - public DefaultTextProvider() { - } - - @Inject - public void setLocalizedTextProvider(LocalizedTextProvider localizedTextProvider) { - this.localizedTextProvider = localizedTextProvider; - } - - public boolean hasKey(String key) { - return getText(key) != null; - } - - public String getText(String key) { - return localizedTextProvider.findDefaultText(key, ActionContext.getContext().getLocale()); - } - - public String getText(String key, String defaultValue) { - String text = getText(key); - if (text == null) { - return defaultValue; - } - return text; - } - - public String getText(String key, List args) { - Object[] params; - if (args != null) { - params = args.toArray(); - } else { - params = EMPTY_ARGS; - } - - return localizedTextProvider.findDefaultText(key, ActionContext.getContext().getLocale(), params); - } - - public String getText(String key, String[] args) { - Object[] params; - if (args != null) { - params = args; - } else { - params = EMPTY_ARGS; - } - - return localizedTextProvider.findDefaultText(key, ActionContext.getContext().getLocale(), params); - } - - public String getText(String key, String defaultValue, List args) { - String text = getText(key, args); - if(text == null && defaultValue == null) { - defaultValue = key; - } - if (text == null && defaultValue != null) { - - MessageFormat format = new MessageFormat(defaultValue); - format.setLocale(ActionContext.getContext().getLocale()); - format.applyPattern(defaultValue); - - Object[] params; - if (args != null) { - params = args.toArray(); - } else { - params = EMPTY_ARGS; - } - - return format.format(params); - } - return text; - } - - public String getText(String key, String defaultValue, String[] args) { - String text = getText(key, args); - if (text == null) { - MessageFormat format = new MessageFormat(defaultValue); - format.setLocale(ActionContext.getContext().getLocale()); - format.applyPattern(defaultValue); - - if (args == null) { - return format.format(EMPTY_ARGS); - } - - return format.format(args); - } - return text; - } - - - public String getText(String key, String defaultValue, String obj) { - List args = new ArrayList<>(1); - args.add(obj); - return getText(key, defaultValue, args); - } - - public String getText(String key, String defaultValue, List args, ValueStack stack) { - //we're not using the value stack here - return getText(key, defaultValue, args); - } - - public String getText(String key, String defaultValue, String[] args, ValueStack stack) { - //we're not using the value stack here - List values = new ArrayList(Arrays.asList(args)); - return getText(key, defaultValue, values); - } - - public ResourceBundle getTexts(String bundleName) { - return localizedTextProvider.findResourceBundle(bundleName, ActionContext.getContext().getLocale()); - } - - public ResourceBundle getTexts() { - return null; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/FileManager.java b/core/src/main/java/com/opensymphony/xwork2/FileManager.java deleted file mode 100644 index 5c6806b8c4..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/FileManager.java +++ /dev/null @@ -1,75 +0,0 @@ -package com.opensymphony.xwork2; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Collection; - -/** - * Basic interface to access file on the File System and to monitor changes - */ -public interface FileManager { - - /** - * Enables configs reloading when config file changed - * - * @param reloadingConfigs {@link XWorkConstants#RELOAD_XML_CONFIGURATION} - */ - void setReloadingConfigs(boolean reloadingConfigs); - - /** - * Checks if given file changed and must be reloaded if {@link #setReloadingConfigs(boolean)} is true - * - * @param fileName to check - * @return true if file changed - */ - boolean fileNeedsReloading(String fileName); - - /** - * Checks if file represented by provided URL should be reloaded - * - * @param fileUrl url to a file - * @return true if file exists and should be reloaded, if url is null return false - */ - boolean fileNeedsReloading(URL fileUrl); - - /** - * Loads opens the named file and returns the InputStream - * - * @param fileUrl - the URL of the file to open - * @return an InputStream of the file contents or null - * @throws IllegalArgumentException if there is no file with the given file name - */ - InputStream loadFile(URL fileUrl); - - /** - * Adds file to list of monitored files if {@link #setReloadingConfigs(boolean)} is true - * - * @param fileUrl {@link URL} to file to be monitored - */ - void monitorFile(URL fileUrl); - - /** - * Convert URLs to URLs with "file" protocol - * @param url URL to convert to a jar url - * @return a URL to a file, or null if the URL external form cannot be parsed - */ - URL normalizeToFileProtocol(URL url); - - /** - * Indicate if given implementation supports current OS File System - * - * @return true if supports current OS File System - */ - boolean support(); - - /** - * User's implementation should return false as then it will be taken in first place - * - * @return true if it's a framework provided implementation - */ - boolean internal(); - - Collection getAllPhysicalUrls(URL url) throws IOException; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/FileManagerFactory.java b/core/src/main/java/com/opensymphony/xwork2/FileManagerFactory.java deleted file mode 100644 index f0eafc09ac..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/FileManagerFactory.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.opensymphony.xwork2; - -/** - * Factory that creates FileManager, default to {@link com.opensymphony.xwork2.util.fs.DefaultFileManager} - */ -public interface FileManagerFactory { - - void setReloadingConfigs(String reloadingConfigs); - - FileManager getFileManager(); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/InvalidMetadataException.java b/core/src/main/java/com/opensymphony/xwork2/InvalidMetadataException.java deleted file mode 100644 index eb556f5a48..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/InvalidMetadataException.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -/** - * InvalidMetadataException - * - * @author Rainer Hermanns - * @version $Id$ - */ -public class InvalidMetadataException extends RuntimeException { - - /** - * Create a new InvalidMetadataException with the supplied error message. - * - * @param msg the error message - */ - public InvalidMetadataException(String msg) { - super(msg); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/LocaleProvider.java b/core/src/main/java/com/opensymphony/xwork2/LocaleProvider.java deleted file mode 100644 index 9efcfae95e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/LocaleProvider.java +++ /dev/null @@ -1,58 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import java.util.Locale; - - -/** - * Indicates that the implementing class can provide its own {@link Locale}. - * - *

    - * This is useful for when an action may wish override the default locale. All that is - * needed is to implement this interface and return your own custom locale. - * The {@link TextProvider} interface uses this interface heavily for retrieving - * internationalized messages from resource bundles. - *

    - * - * @author Jason Carreira - */ -public interface LocaleProvider { - - /** - * Gets the provided locale. - * - * @return the locale. - */ - Locale getLocale(); - - /** - * Validates if provided string is a valid {@link Locale} - * - * @param localeStr a String representing locale, e.g. en_EN - * @return true if valid - */ - boolean isValidLocaleString(String localeStr); - - /** - * Validates if provided {@link Locale} is value - * - * @param locale instance of {@link Locale} to validate - * @return true if valid - */ - boolean isValidLocale(Locale locale); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/LocaleProviderFactory.java b/core/src/main/java/com/opensymphony/xwork2/LocaleProviderFactory.java deleted file mode 100644 index 930418d9f5..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/LocaleProviderFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -/** - * Allows delegate creation of {@link LocaleProvider} to another implementation provided - * by a user. It also allows avoid problems with too many dependencies as {@link LocaleProvider} - * is implemented by the {@link ActionSupport} which can be defined as a bean in Spring. - */ -public interface LocaleProviderFactory { - - /** - * Create a new instance of {@link LocaleProvider}. - * - * @return the localeProvider. - */ - LocaleProvider createLocaleProvider(); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/LocalizedTextProvider.java b/core/src/main/java/com/opensymphony/xwork2/LocalizedTextProvider.java deleted file mode 100644 index 85c5458e3b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/LocalizedTextProvider.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.util.ValueStack; - -import java.io.Serializable; -import java.util.Locale; -import java.util.ResourceBundle; - -public interface LocalizedTextProvider extends Serializable { - - String findDefaultText(String aTextName, Locale locale); - - String findDefaultText(String aTextName, Locale locale, Object[] params); - - ResourceBundle findResourceBundle(String aBundleName, Locale locale); - - String findText(Class aClass, String aTextName, Locale locale); - - String findText(Class aClass, String aTextName, Locale locale, String defaultMessage, Object[] args); - - String findText(Class aClass, String aTextName, Locale locale, String defaultMessage, Object[] args, ValueStack valueStack); - - String findText(ResourceBundle bundle, String aTextName, Locale locale); - - String findText(ResourceBundle bundle, String aTextName, Locale locale, String defaultMessage, Object[] args); - - String findText(ResourceBundle bundle, String aTextName, Locale locale, String defaultMessage, Object[] args, ValueStack valueStack); - - void addDefaultResourceBundle(String resourceBundleName); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java b/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java deleted file mode 100644 index 2f5f6c7ef2..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ModelDriven.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - - -/** - * ModelDriven Actions provide a model object to be pushed onto the ValueStack - * in addition to the Action itself, allowing a FormBean type approach like Struts. - * - * @author Jason Carreira - */ -public interface ModelDriven { - - /** - * Gets the model to be pushed onto the ValueStack instead of the Action itself. - * - * @return the model - */ - T getModel(); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/Preparable.java b/core/src/main/java/com/opensymphony/xwork2/Preparable.java deleted file mode 100644 index 58a2412cda..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/Preparable.java +++ /dev/null @@ -1,35 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - - -/** - * Preparable Actions will have their prepare() method called if the {@link com.opensymphony.xwork2.interceptor.PrepareInterceptor} - * is applied to the ActionConfig. - * - * @author Jason Carreira - * @see com.opensymphony.xwork2.interceptor.PrepareInterceptor - */ -public interface Preparable { - - /** - * This method is called to allow the action to prepare itself. - * - * @throws Exception thrown if a system level exception occurs. - */ - void prepare() throws Exception; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ResourceBundleTextProvider.java b/core/src/main/java/com/opensymphony/xwork2/ResourceBundleTextProvider.java deleted file mode 100644 index 1415e716e7..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ResourceBundleTextProvider.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import java.util.ResourceBundle; - -/** - * Extension Interface for TextProvider to help supporting ResourceBundles. - * - * @author Rene Gielen - */ -public interface ResourceBundleTextProvider extends TextProvider { - - /** - * Set the resource bundle to use. - * - * @param bundle the bundle to use. - */ - void setBundle(ResourceBundle bundle); - - /** - * Set the class to use for reading the resource bundle. - * - * @param clazz the class to use for loading. - */ - void setClazz(Class clazz); - - /** - * Set the LocaleProvider to use. - * - * @param localeProvider the LocaleProvider to use. - */ - void setLocaleProvider(LocaleProvider localeProvider); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/Result.java b/core/src/main/java/com/opensymphony/xwork2/Result.java deleted file mode 100644 index c8d8bed759..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/Result.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import java.io.Serializable; - - -/** - * All results (except for Action.NONE) of an {@link Action} are mapped to a View implementation. - * - *

    - * Examples of Views might be: - *

    - * - *
      - *
    • SwingPanelView - pops up a new Swing panel
    • - *
    • ActionChainView - executes another action
    • - *
    • SerlvetRedirectView - redirects the HTTP response to a URL
    • - *
    • ServletDispatcherView - dispatches the HTTP response to a URL
    • - *
    - * - * @author plightbo - */ -public interface Result extends Serializable { - - /** - * Represents a generic interface for all action execution results. - * Whether that be displaying a webpage, generating an email, sending a JMS message, etc. - * - * @param invocation the invocation context. - * @throws Exception can be thrown. - */ - public void execute(ActionInvocation invocation) throws Exception; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java b/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java deleted file mode 100644 index 823e764bef..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/TestNGXWorkTestCase.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.ConfigurationManager; -import com.opensymphony.xwork2.config.ConfigurationProvider; -import com.opensymphony.xwork2.config.impl.MockConfiguration; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.util.XWorkTestCaseHelper; -import org.testng.annotations.AfterTest; -import org.testng.annotations.BeforeTest; - -/** - * Base test class for TestNG unit tests. Provides common XWork variables - * and performs XWork setup and teardown processes - */ -public class TestNGXWorkTestCase { - - protected ConfigurationManager configurationManager; - protected Configuration configuration; - protected Container container; - protected ActionProxyFactory actionProxyFactory; - - @BeforeTest - protected void setUp() throws Exception { - configurationManager = XWorkTestCaseHelper.setUp(); - configuration = new MockConfiguration(); - ((MockConfiguration) configuration).selfRegister(); - container = configuration.getContainer(); - actionProxyFactory = container.getInstance(ActionProxyFactory.class); - } - - @AfterTest - protected void tearDown() throws Exception { - XWorkTestCaseHelper.tearDown(configurationManager); - configurationManager = null; - configuration = null; - container = null; - actionProxyFactory = null; - } - - protected void loadConfigurationProviders(ConfigurationProvider... providers) { - configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers); - configuration = configurationManager.getConfiguration(); - container = configuration.getContainer(); - actionProxyFactory = container.getInstance(ActionProxyFactory.class); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/TextProviderFactory.java b/core/src/main/java/com/opensymphony/xwork2/TextProviderFactory.java deleted file mode 100644 index 4d55d6c0ae..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/TextProviderFactory.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.inject.Inject; - -import java.util.ResourceBundle; - -/** - * This factory enables users to provide and correctly initialize a custom TextProvider. - * - * @author Oleg Gorobets - * @author Rene Gielen - */ -public class TextProviderFactory { - - private TextProvider textProvider; - private LocaleProviderFactory localeProviderFactory; - private LocalizedTextProvider localizedTextProvider; - - @Inject - public void setTextProvider(TextProvider textProvider) { - this.textProvider = textProvider; - } - - @Inject - public void setLocaleProviderFactory(LocaleProviderFactory localeProviderFactory) { - this.localeProviderFactory = localeProviderFactory; - } - - @Inject - public void setLocalizedTextProvider(LocalizedTextProvider localizedTextProvider) { - this.localizedTextProvider = localizedTextProvider; - } - - public TextProvider createInstance(Class clazz) { - TextProvider instance = getTextProvider(clazz); - if (instance instanceof ResourceBundleTextProvider) { - ((ResourceBundleTextProvider) instance).setClazz(clazz); - ((ResourceBundleTextProvider) instance).setLocaleProvider(localeProviderFactory.createLocaleProvider()); - } - return instance; - } - - public TextProvider createInstance(ResourceBundle bundle) { - TextProvider instance = getTextProvider(bundle); - if (instance instanceof ResourceBundleTextProvider) { - ((ResourceBundleTextProvider) instance).setBundle(bundle); - ((ResourceBundleTextProvider) instance).setLocaleProvider(localeProviderFactory.createLocaleProvider()); - } - return instance; - } - - protected TextProvider getTextProvider(Class clazz) { - if (this.textProvider == null) { - return new TextProviderSupport(clazz, localeProviderFactory.createLocaleProvider(), localizedTextProvider); - } else { - return textProvider; - } - } - - private TextProvider getTextProvider(ResourceBundle bundle) { - if (this.textProvider == null) { - return new TextProviderSupport(bundle, localeProviderFactory.createLocaleProvider(), localizedTextProvider); - } - return textProvider; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/Unchainable.java b/core/src/main/java/com/opensymphony/xwork2/Unchainable.java deleted file mode 100644 index 19d88ef4fb..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/Unchainable.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2; - -/** - * Simple marker interface to indicate an object should not have its properties copied during chaining. - * - * @see com.opensymphony.xwork2.interceptor.ChainingInterceptor - */ -public interface Unchainable { -} diff --git a/core/src/main/java/com/opensymphony/xwork2/UnknownHandler.java b/core/src/main/java/com/opensymphony/xwork2/UnknownHandler.java deleted file mode 100644 index 51556d6a44..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/UnknownHandler.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.config.entities.ActionConfig; - -/** - * Handles cases when the result or action is unknown. - * - *

    - * This allows other classes like Struts plugins to provide intelligent defaults easier. - *

    - */ -public interface UnknownHandler { - - /** - * Handles the case when an action configuration is unknown. Implementations can return a new ActionConfig - * to be used to process the request. - * - * @param namespace The namespace - * @param actionName The action name - * @return An generated ActionConfig, can return null - * @throws XWorkException in case of errors - */ - ActionConfig handleUnknownAction(String namespace, String actionName) throws XWorkException; - - /** - * Handles the case when a result cannot be found for an action and result code. - * - * @param actionContext The action context - * @param actionName The action name - * @param actionConfig The action config - * @param resultCode The returned result code - * @return A result to be executed, can return null - * @throws XWorkException in case of errors - */ - Result handleUnknownResult(ActionContext actionContext, String actionName, ActionConfig actionConfig, String resultCode) throws XWorkException; - - /** - * Handles the case when an action method cannot be found. This method is responsible both for finding the method and executing it. - * - * @since 2.1 - * @param action The action object - * @param methodName The method name to call - * @return The result returned from invoking the action method, can return null if this instance cannot - * handle such methodName to allow other handlers give a chance - */ - Object handleUnknownActionMethod(Object action, String methodName); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/UnknownHandlerManager.java b/core/src/main/java/com/opensymphony/xwork2/UnknownHandlerManager.java deleted file mode 100644 index d8cce9f78b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/UnknownHandlerManager.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.config.entities.ActionConfig; - -import java.util.List; - -/** - * An unknown handler manager contains a list of UnknownHandler and iterates on them by order - * - * @see com.opensymphony.xwork2.DefaultUnknownHandlerManager - */ -public interface UnknownHandlerManager { - - Result handleUnknownResult(ActionContext actionContext, String actionName, ActionConfig actionConfig, String resultCode); - - /** - * Tries to handle passed methodName if cannot find method should re - * - * @param action Action's instance - * @param methodName method name to handle - * @return Result representing result of given action method - * @throws NoSuchMethodException if method can be handled by defined UnknownHandlers - */ - Object handleUnknownMethod(Object action, String methodName) throws NoSuchMethodException; - - ActionConfig handleUnknownAction(String namespace, String actionName); - - boolean hasUnknownHandlers(); - - List getUnknownHandlers(); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/Validateable.java b/core/src/main/java/com/opensymphony/xwork2/Validateable.java deleted file mode 100644 index 889a284401..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/Validateable.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - - -/** - * Provides an interface in which a call for a validation check can be done. - * - * @author Jason Carreira - * @see ActionSupport - * @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor - */ -public interface Validateable { - - /** - * Performs validation. - */ - void validate(); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/XWorkConstants.java b/core/src/main/java/com/opensymphony/xwork2/XWorkConstants.java deleted file mode 100644 index bc532d0d5d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/XWorkConstants.java +++ /dev/null @@ -1,31 +0,0 @@ -package com.opensymphony.xwork2; - -/** - * Constants used across framework - */ -public final class XWorkConstants { - - public static final String COLLECTION_CONVERTER = "collectionConverter"; - public static final String DATE_CONVERTER = "dateConverter"; - public static final String NUMBER_CONVERTER = "numberConverter"; - public static final String STRING_CONVERTER = "stringConverter"; - public static final String ARRAY_CONVERTER = "arrayConverter"; - public static final String DEV_MODE = "devMode"; - public static final String LOG_MISSING_PROPERTIES = "logMissingProperties"; - public static final String ENABLE_OGNL_EXPRESSION_CACHE = "enableOGNLExpressionCache"; - public static final String ENABLE_OGNL_EVAL_EXPRESSION = "enableOGNLEvalExpression"; - public static final String RELOAD_XML_CONFIGURATION = "reloadXmlConfiguration"; - public static final String ALLOW_STATIC_METHOD_ACCESS = "allowStaticMethodAccess"; - public static final String XWORK_LOGGER_FACTORY = "xwork.loggerFactory"; - - public static final String OGNL_EXCLUDED_CLASSES = "ognlExcludedClasses"; - public static final String OGNL_EXCLUDED_PACKAGE_NAME_PATTERNS = "ognlExcludedPackageNamePatterns"; - public static final String OGNL_EXCLUDED_PACKAGE_NAMES = "ognlExcludedPackageNames"; - - public static final String ADDITIONAL_EXCLUDED_PATTERNS = "additionalExcludedPatterns"; - public static final String ADDITIONAL_ACCEPTED_PATTERNS = "additionalAcceptedPatterns"; - - public static final String OVERRIDE_EXCLUDED_PATTERNS = "overrideExcludedPatterns"; - public static final String OVERRIDE_ACCEPTED_PATTERNS = "overrideAcceptedPatterns"; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/XWorkException.java b/core/src/main/java/com/opensymphony/xwork2/XWorkException.java deleted file mode 100644 index ec3ad3e82b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/XWorkException.java +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.util.location.Locatable; -import com.opensymphony.xwork2.util.location.Location; -import com.opensymphony.xwork2.util.location.LocationUtils; - - -/** - * A generic runtime exception that optionally contains Location information - * - * @author Jason Carreira - */ -public class XWorkException extends RuntimeException implements Locatable { - - private Location location; - - - /** - * Constructs a XWorkException with no detail message. - */ - public XWorkException() { - } - - /** - * Constructs a XWorkException with the specified - * detail message. - * - * @param s the detail message. - */ - public XWorkException(String s) { - this(s, null, null); - } - - /** - * Constructs a XWorkException with the specified - * detail message and target. - * - * @param s the detail message. - * @param target the target of the exception. - */ - public XWorkException(String s, Object target) { - this(s, null, target); - } - - /** - * Constructs a XWorkException with the root cause - * - * @param cause The wrapped exception - */ - public XWorkException(Throwable cause) { - this(null, cause, null); - } - - /** - * Constructs a XWorkException with the root cause and target - * - * @param cause The wrapped exception - * @param target The target of the exception - */ - public XWorkException(Throwable cause, Object target) { - this(null, cause, target); - } - - /** - * Constructs a XWorkException with the specified - * detail message and exception cause. - * - * @param s the detail message. - * @param cause the wrapped exception - */ - public XWorkException(String s, Throwable cause) { - this(s, cause, null); - } - - - /** - * Constructs a XWorkException with the specified - * detail message, cause, and target - * - * @param s the detail message. - * @param cause The wrapped exception - * @param target The target of the exception - */ - public XWorkException(String s, Throwable cause, Object target) { - super(s, cause); - - this.location = LocationUtils.getLocation(target); - if (this.location == Location.UNKNOWN) { - this.location = LocationUtils.getLocation(cause); - } - } - - /** - * Gets the location of the error, if available - * - * @return the location, null if not available - */ - public Location getLocation() { - return this.location; - } - - - /** - * Returns a short description of this throwable object, including the - * location. If no detailed message is available, it will use the message - * of the underlying exception if available. - * - * @return a string representation of this Throwable. - */ - @Override - public String toString() { - String msg = getMessage(); - if (msg == null && getCause() != null) { - msg = getCause().getMessage(); - } - - if (location != null) { - if (msg != null) { - return msg + " - " + location.toString(); - } else { - return location.toString(); - } - } else { - return msg; - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java b/core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java deleted file mode 100644 index 90b53d2135..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/XWorkJUnit4TestCase.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.ConfigurationManager; -import com.opensymphony.xwork2.config.ConfigurationProvider; -import com.opensymphony.xwork2.inject.*; -import com.opensymphony.xwork2.test.StubConfigurationProvider; -import com.opensymphony.xwork2.util.XWorkTestCaseHelper; -import com.opensymphony.xwork2.util.location.LocatableProperties; -import org.junit.After; -import org.junit.Before; - -public abstract class XWorkJUnit4TestCase { - - protected ConfigurationManager configurationManager; - protected Configuration configuration; - protected Container container; - protected ActionProxyFactory actionProxyFactory; - - @Before - public void setUp() throws Exception { - configurationManager = XWorkTestCaseHelper.setUp(); - configuration = configurationManager.getConfiguration(); - container = configuration.getContainer(); - actionProxyFactory = container.getInstance(ActionProxyFactory.class); - } - - @After - public void tearDown() throws Exception { - XWorkTestCaseHelper.tearDown(configurationManager); - configurationManager = null; - configuration = null; - container = null; - actionProxyFactory = null; - } - - protected void loadConfigurationProviders(ConfigurationProvider... providers) { - configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers); - configuration = configurationManager.getConfiguration(); - container = configuration.getContainer(); - actionProxyFactory = container.getInstance(ActionProxyFactory.class); - } - - protected void loadButAdd(final Class type, final Object impl) { - loadButAdd(type, Container.DEFAULT_NAME, impl); - } - - protected void loadButAdd(final Class type, final String name, final Object impl) { - loadConfigurationProviders(new StubConfigurationProvider() { - @Override - public void register(ContainerBuilder builder, - LocatableProperties props) throws ConfigurationException { - builder.factory(type, name, new Factory() { - public Object create(Context context) throws Exception { - return impl; - } - - }, Scope.SINGLETON); - } - }); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java b/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java deleted file mode 100644 index c9b4e32f97..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/XWorkTestCase.java +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.ConfigurationManager; -import com.opensymphony.xwork2.config.ConfigurationProvider; -import com.opensymphony.xwork2.inject.*; -import com.opensymphony.xwork2.test.StubConfigurationProvider; -import com.opensymphony.xwork2.util.XWorkTestCaseHelper; -import com.opensymphony.xwork2.util.location.LocatableProperties; -import junit.framework.TestCase; - - -/** - * Base JUnit TestCase to extend for XWork specific JUnit tests. Uses - * the generic test setup for logic. - * - * @author plightbo - */ -public abstract class XWorkTestCase extends TestCase { - - protected ConfigurationManager configurationManager; - protected Configuration configuration; - protected Container container; - protected ActionProxyFactory actionProxyFactory; - - public XWorkTestCase() { - super(); - } - - @Override - protected void setUp() throws Exception { - configurationManager = XWorkTestCaseHelper.setUp(); - configuration = configurationManager.getConfiguration(); - container = configuration.getContainer(); - actionProxyFactory = container.getInstance(ActionProxyFactory.class); - } - - @Override - protected void tearDown() throws Exception { - XWorkTestCaseHelper.tearDown(configurationManager); - configurationManager = null; - configuration = null; - container = null; - actionProxyFactory = null; - } - - protected void loadConfigurationProviders(ConfigurationProvider... providers) { - configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers); - configuration = configurationManager.getConfiguration(); - container = configuration.getContainer(); - actionProxyFactory = container.getInstance(ActionProxyFactory.class); - } - - protected void loadButAdd(final Class type, final Object impl) { - loadButAdd(type, Container.DEFAULT_NAME, impl); - } - - protected void loadButAdd(final Class type, final String name, final Object impl) { - loadConfigurationProviders(new StubConfigurationProvider() { - @Override - public void register(ContainerBuilder builder, - LocatableProperties props) throws ConfigurationException { - builder.factory(type, name, new Factory() { - public Object create(Context context) throws Exception { - return impl; - } - - }, Scope.SINGLETON); - } - }); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/BeanSelectionProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/BeanSelectionProvider.java deleted file mode 100644 index d6cef8b41d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/BeanSelectionProvider.java +++ /dev/null @@ -1,8 +0,0 @@ -package com.opensymphony.xwork2.config; - -/** - * When implemented allows to alias already existing beans - */ -public interface BeanSelectionProvider extends ConfigurationProvider { - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/Configuration.java b/core/src/main/java/com/opensymphony/xwork2/config/Configuration.java deleted file mode 100644 index 9af002fde0..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/Configuration.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config; - -import com.opensymphony.xwork2.config.entities.PackageConfig; -import com.opensymphony.xwork2.config.entities.UnknownHandlerConfig; -import com.opensymphony.xwork2.inject.Container; - -import java.io.Serializable; -import java.util.List; -import java.util.Map; -import java.util.Set; - - -/** - * XWork configuration. - * - * @author Mike - */ -public interface Configuration extends Serializable { - - void rebuildRuntimeConfiguration(); - - PackageConfig getPackageConfig(String name); - - Set getPackageConfigNames(); - - Map getPackageConfigs(); - - /** - * The current runtime configuration. Currently, if changes have been made to the Configuration since the last - * time buildRuntimeConfiguration() was called, you'll need to make sure to. - * - * @return the current runtime configuration - */ - RuntimeConfiguration getRuntimeConfiguration(); - - void addPackageConfig(String name, PackageConfig packageConfig); - - /** - * Removes a package from the the list of packages. Changes to the configuration won't take effect until buildRuntimeConfiguration - * is called. - * @param packageName the name of the package to remove - * @return the package removed (if any) - */ - PackageConfig removePackageConfig(String packageName); - - /** - * Allow the Configuration to clean up any resources that have been used. - */ - void destroy(); - - /** - * @since 2.1 - * @param containerProviders list of container providers - * @return list of package providers - * @throws ConfigurationException in case of any configuration errors - */ - List reloadContainer(List containerProviders) throws ConfigurationException; - - /** - * @return the container - */ - Container getContainer(); - - Set getLoadedFileNames(); - - /** - * @since 2.1 - * @return list of unknown handlers - */ - List getUnknownHandlerStack(); - - /** - * @since 2.1 - * @param unknownHandlerStack list of unknown handlers - */ - void setUnknownHandlerStack(List unknownHandlerStack); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationException.java b/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationException.java deleted file mode 100644 index af505f72e3..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationException.java +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config; - -import com.opensymphony.xwork2.XWorkException; - - -/** - * ConfigurationException - * - * @author Jason Carreira - */ -public class ConfigurationException extends XWorkException { - - /** - * Constructs a ConfigurationException with no detail message. - */ - public ConfigurationException() { - } - - /** - * Constructs a ConfigurationException with the specified - * detail message. - * - * @param s the detail message. - */ - public ConfigurationException(String s) { - super(s); - } - - /** - * Constructs a ConfigurationException with the specified - * detail message. - * - * @param s the detail message. - * @param target the target object - */ - public ConfigurationException(String s, Object target) { - super(s, target); - } - - /** - * Constructs a ConfigurationException with no detail message. - * - * @param cause the cause of the exception - */ - public ConfigurationException(Throwable cause) { - super(cause); - } - - /** - * Constructs a ConfigurationException with no detail message. - * @param cause the cause of the exception - * @param target the target object - */ - public ConfigurationException(Throwable cause, Object target) { - super(cause, target); - } - - /** - * Constructs a ConfigurationException with the specified - * detail message. - * - * @param s the detail message. - * @param cause the cause of the exception - */ - public ConfigurationException(String s, Throwable cause) { - super(s, cause); - } - - /** - * Constructs a ConfigurationException with the specified - * detail message. - * - * @param s the detail message. - * @param cause the cause of the exception - * @param target the target object - */ - public ConfigurationException(String s, Throwable cause, Object target) { - super(s, cause, target); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationManager.java b/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationManager.java deleted file mode 100644 index f937e9d668..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationManager.java +++ /dev/null @@ -1,231 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config; - -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.config.impl.DefaultConfiguration; -import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider; -import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantLock; - - -/** - * ConfigurationManager - central for XWork Configuration management, including - * its ConfigurationProvider. - * - * @author Jason Carreira - * @author tm_jee - * @version $Date$ $Id$ - */ -public class ConfigurationManager { - - protected static final Logger LOG = LogManager.getLogger(ConfigurationManager.class); - protected Configuration configuration; - protected Lock providerLock = new ReentrantLock(); - private List containerProviders = new CopyOnWriteArrayList<>(); - private List packageProviders = new CopyOnWriteArrayList<>(); - protected String defaultFrameworkBeanName; - private boolean providersChanged = false; - private boolean reloadConfigs = true; // for the first time - - public ConfigurationManager(String name) { - this.defaultFrameworkBeanName = name; - } - - /** - * @return the current XWork configuration object. By default an instance of DefaultConfiguration will be returned - * - * @see com.opensymphony.xwork2.config.impl.DefaultConfiguration - */ - public synchronized Configuration getConfiguration() { - if (configuration == null) { - setConfiguration(createConfiguration(defaultFrameworkBeanName)); - try { - configuration.reloadContainer(getContainerProviders()); - } catch (ConfigurationException e) { - setConfiguration(null); - throw new ConfigurationException("Unable to load configuration.", e); - } - } else { - conditionalReload(); - } - - return configuration; - } - - protected Configuration createConfiguration(String beanName) { - return new DefaultConfiguration(beanName); - } - - public synchronized void setConfiguration(Configuration configuration) { - this.configuration = configuration; - } - - /** - *

    - * Get the current list of ConfigurationProviders. If no custom ConfigurationProviders have been added, this method - * will return a list containing only the default ConfigurationProvider, XMLConfigurationProvider. If a custom - * ConfigurationProvider has been added, then the XmlConfigurationProvider must be added by hand. - *

    - * - *

    - * TODO: The lazy instantiation of XmlConfigurationProvider should be refactored to be elsewhere. The behavior described above seems unintuitive. - *

    - * - * @return the list of registered ConfigurationProvider objects - * @see ConfigurationProvider - */ - public List getContainerProviders() { - providerLock.lock(); - try { - if (containerProviders.size() == 0) { - containerProviders.add(new XWorkConfigurationProvider()); - containerProviders.add(new XmlConfigurationProvider("xwork.xml", false)); - } - - return containerProviders; - } finally { - providerLock.unlock(); - } - } - - /** - * Set the list of configuration providers - * - * @param containerProviders list of {@link ConfigurationProvider} to be set - */ - public void setContainerProviders(List containerProviders) { - providerLock.lock(); - try { - this.containerProviders = new CopyOnWriteArrayList<>(containerProviders); - providersChanged = true; - } finally { - providerLock.unlock(); - } - } - - /** - * adds a configuration provider to the List of ConfigurationProviders. a given ConfigurationProvider may be added - * more than once - * - * @param provider the ConfigurationProvider to register - */ - public void addContainerProvider(ContainerProvider provider) { - if (!containerProviders.contains(provider)) { - containerProviders.add(provider); - providersChanged = true; - } - } - - public void clearContainerProviders() { - for (ContainerProvider containerProvider : containerProviders) { - clearContainerProvider(containerProvider); - } - containerProviders.clear(); - providersChanged = true; - } - - private void clearContainerProvider(ContainerProvider containerProvider) { - try { - containerProvider.destroy(); - } catch (Exception e) { - LOG.warn("Error while destroying container provider [{}]", containerProvider.toString(), e); - } - } - - /** - * Destroy its managing Configuration instance - */ - public synchronized void destroyConfiguration() { - clearContainerProviders(); // let's destroy the ConfigurationProvider first - containerProviders = new CopyOnWriteArrayList(); - if (configuration != null) - configuration.destroy(); // let's destroy it first, before nulling it. - configuration = null; - } - - - /** - * Reloads the Configuration files if the configuration files indicate that they need to be reloaded. - */ - public synchronized void conditionalReload() { - if (reloadConfigs || providersChanged) { - LOG.debug("Checking ConfigurationProviders for reload."); - List providers = getContainerProviders(); - boolean reload = needReloadContainerProviders(providers); - if (!reload) { - reload = needReloadPackageProviders(); - } - if (reload) { - reloadProviders(providers); - } - updateReloadConfigsFlag(); - providersChanged = false; - } - } - - private void updateReloadConfigsFlag() { - reloadConfigs = Boolean.parseBoolean(configuration.getContainer().getInstance(String.class, XWorkConstants.RELOAD_XML_CONFIGURATION)); - if (LOG.isDebugEnabled()) { - LOG.debug("Updating [{}], current value is [{}], new value [{}]", - XWorkConstants.RELOAD_XML_CONFIGURATION, String.valueOf(reloadConfigs), String.valueOf(reloadConfigs)); - } - } - - private boolean needReloadPackageProviders() { - if (packageProviders != null) { - for (PackageProvider provider : packageProviders) { - if (provider.needsReload()) { - LOG.info("Detected package provider [{}] needs to be reloaded. Reloading all providers.", provider); - return true; - } - } - } - return false; - } - - private boolean needReloadContainerProviders(List providers) { - for (ContainerProvider provider : providers) { - if (provider.needsReload()) { - LOG.info("Detected container provider [{}] needs to be reloaded. Reloading all providers.", provider); - return true; - } - } - return false; - } - - private void reloadProviders(List providers) { - for (ContainerProvider containerProvider : containerProviders) { - try { - containerProvider.destroy(); - } catch (Exception e) { - LOG.warn("error while destroying configuration provider [{}]", containerProvider, e); - } - } - packageProviders = this.configuration.reloadContainer(providers); - } - - public synchronized void reload() { - packageProviders = getConfiguration().reloadContainer(getContainerProviders()); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationProvider.java deleted file mode 100644 index 146532bf57..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationProvider.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config; - -/** - * Interface to be implemented by all forms of XWork configuration classes. - */ -public interface ConfigurationProvider extends ContainerProvider, PackageProvider { -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationUtil.java b/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationUtil.java deleted file mode 100644 index e7ba7a6167..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/ConfigurationUtil.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config; - -import com.opensymphony.xwork2.config.entities.PackageConfig; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.ArrayList; -import java.util.Collections; -import java.util.List; -import java.util.StringTokenizer; - -/** - * ConfigurationUtil - * - * @author Jason Carreira Created May 23, 2003 11:22:49 PM - */ -public class ConfigurationUtil { - - private static final Logger LOG = LogManager.getLogger(ConfigurationUtil.class); - - private ConfigurationUtil() { - } - - /** - * Get the {@link PackageConfig} elements with the specified names. - * @param configuration Configuration from which to find the package elements - * @param parent Comma separated list of parent package names - * @return The package elements that correspond to the names in the {@code parent} parameter. - */ - public static List buildParentsFromString(Configuration configuration, String parent) { - List parentPackageNames = buildParentListFromString(parent); - List parentPackageConfigs = new ArrayList<>(); - for (String parentPackageName : parentPackageNames) { - PackageConfig parentPackageContext = configuration.getPackageConfig(parentPackageName); - - if (parentPackageContext != null) { - parentPackageConfigs.add(parentPackageContext); - } - } - - return parentPackageConfigs; - } - - /** - * Splits the string into a list using a comma as the token separator. - * @param parent The comma separated string. - * @return A list of tokens from the specified string. - */ - public static List buildParentListFromString(String parent) { - if (StringUtils.isEmpty(parent)) { - return Collections.emptyList(); - } - - StringTokenizer tokenizer = new StringTokenizer(parent, ","); - List parents = new ArrayList<>(); - - while (tokenizer.hasMoreTokens()) { - String parentName = tokenizer.nextToken().trim(); - - if (StringUtils.isNotEmpty(parentName)) { - parents.add(parentName); - } - } - - return parents; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/ContainerProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/ContainerProvider.java deleted file mode 100644 index de943f0a19..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/ContainerProvider.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config; - -import com.opensymphony.xwork2.inject.ContainerBuilder; -import com.opensymphony.xwork2.util.location.LocatableProperties; - - -/** - * Provides beans and constants/properties for the Container - * - * @since 2.1 - */ -public interface ContainerProvider { - - /** - * Called before removed from the configuration manager - */ - public void destroy(); - - /** - * Initializes with the configuration - * @param configuration The configuration - * @throws ConfigurationException If anything goes wrong - */ - public void init(Configuration configuration) throws ConfigurationException; - - /** - * Tells whether the ContainerProvider should reload its configuration - * - * @return true, whether the ContainerProvider should reload its configuration, falseotherwise. - */ - public boolean needsReload(); - - /** - * Registers beans and properties for the Container - * - * @param builder The builder to register beans with - * @param props The properties to register constants with - * @throws ConfigurationException If anything goes wrong - */ - public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/FileManagerFactoryProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/FileManagerFactoryProvider.java deleted file mode 100644 index 392b138fcd..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/FileManagerFactoryProvider.java +++ /dev/null @@ -1,33 +0,0 @@ -package com.opensymphony.xwork2.config; - -import com.opensymphony.xwork2.FileManagerFactory; -import com.opensymphony.xwork2.inject.ContainerBuilder; -import com.opensymphony.xwork2.inject.Scope; -import com.opensymphony.xwork2.util.location.LocatableProperties; - -/** - * Allows to specify custom {@link FileManagerFactory} - */ -public class FileManagerFactoryProvider implements ContainerProvider { - - private Class factoryClass; - - public FileManagerFactoryProvider(Class factoryClass) { - this.factoryClass = factoryClass; - } - - public void destroy() { - } - - public void init(Configuration configuration) throws ConfigurationException { - } - - public boolean needsReload() { - return false; - } - - public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { - builder.factory(FileManagerFactory.class, factoryClass.getSimpleName(), factoryClass, Scope.SINGLETON); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/FileManagerProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/FileManagerProvider.java deleted file mode 100644 index 100f458522..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/FileManagerProvider.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.opensymphony.xwork2.config; - -import com.opensymphony.xwork2.FileManager; -import com.opensymphony.xwork2.inject.ContainerBuilder; -import com.opensymphony.xwork2.inject.Scope; -import com.opensymphony.xwork2.util.location.LocatableProperties; - -/** - * Allows to specify custom {@link FileManager} by user - */ -public class FileManagerProvider implements ContainerProvider { - - private Class fileManagerClass; - private String name; - - public FileManagerProvider(Class fileManagerClass, String name) { - this.fileManagerClass = fileManagerClass; - this.name = name; - } - - public void destroy() { - } - - public void init(Configuration configuration) throws ConfigurationException { - } - - public boolean needsReload() { - return false; - } - - public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { - builder.factory(FileManager.class, name, fileManagerClass, Scope.SINGLETON); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/PackageProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/PackageProvider.java deleted file mode 100644 index 9020e3ce74..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/PackageProvider.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config; - -/** - * Provides configuration packages. The separate init and loadPackages calls are due to the need to - * preserve backwards compatibility with the 2.0 {@link ConfigurationProvider} interface - * - * @since 2.1 - */ -public interface PackageProvider { - - /** - * Initializes with the configuration - * @param configuration The configuration - * @throws ConfigurationException If anything goes wrong - */ - void init(Configuration configuration) throws ConfigurationException; - - /** - * Tells whether the PackageProvider should reload its configuration - * - * @return true, whether the PackageProvider should reload its configuration, falseotherwise. - */ - boolean needsReload(); - - /** - * Loads the packages for the configuration. - * @throws ConfigurationException in case of configuration errors - */ - void loadPackages() throws ConfigurationException; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/ReferenceResolverException.java b/core/src/main/java/com/opensymphony/xwork2/config/ReferenceResolverException.java deleted file mode 100644 index 00f1adb7bb..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/ReferenceResolverException.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config; - -import com.opensymphony.xwork2.XWorkException; - - -/** - * Exception when a reference can't be resolved. - * - * @author Mike - */ -public class ReferenceResolverException extends XWorkException { - - public ReferenceResolverException() { - super(); - } - - public ReferenceResolverException(String s) { - super(s); - } - - public ReferenceResolverException(String s, Throwable cause) { - super(s, cause); - } - - public ReferenceResolverException(Throwable cause) { - super(cause); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/RuntimeConfiguration.java b/core/src/main/java/com/opensymphony/xwork2/config/RuntimeConfiguration.java deleted file mode 100644 index f24c766ccb..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/RuntimeConfiguration.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config; - -import com.opensymphony.xwork2.config.entities.ActionConfig; - -import java.io.Serializable; -import java.util.Map; - - -/** - * RuntimeConfiguration - * - * @author Jason Carreira - * Created Feb 25, 2003 10:56:02 PM - */ -public interface RuntimeConfiguration extends Serializable { - - /** - * get the fully expanded ActionConfig for a specified namespace and (action) name - * - * @param namespace the namespace of the Action. if this is null, then the empty namespace, "", will be used - * @param name the name of the Action. may not be null. - * @return the requested ActionConfig or null if there was no ActionConfig associated with the specified namespace - * and name - */ - ActionConfig getActionConfig(String namespace, String name); - - /** - * returns a Map of all the registered ActionConfigs. Again, these ActionConfigs are fully expanded so that any - * inherited interceptors, results, etc. will be included - * - * @return a Map of Map keyed by namespace and name respectively such that - *
    -     *                 ActionConfig config = (ActionConfig)((Map)getActionConfigs.get(namespace)).get(name);
    -     *                 
    - * should return a valid config for valid namespace/name pairs - */ - Map> getActionConfigs(); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/ServletContextAwareConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/ServletContextAwareConfigurationProvider.java deleted file mode 100644 index 506d9063ac..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/ServletContextAwareConfigurationProvider.java +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config; - -import javax.servlet.ServletContext; - -/** - * Dedicated interface to allow inject {@link ServletContext} and perform initialisation based in it - */ -public interface ServletContextAwareConfigurationProvider extends ConfigurationProvider { - - /** - * This is a lazy constructor, called just after class was initiated - * - * @param servletContext current instance of {@link ServletContext} - */ - void initWithContext(ServletContext servletContext); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/ExceptionMappingConfig.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/ExceptionMappingConfig.java deleted file mode 100644 index 21a791e964..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/entities/ExceptionMappingConfig.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.config.entities; - -import com.opensymphony.xwork2.util.location.Located; -import com.opensymphony.xwork2.util.location.Location; - -import java.io.Serializable; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Configuration for exception mapping. - * - * @author Rainer Hermanns - * @author Matthew E. Porter (matthew dot porter at metissian dot com) - */ -public class ExceptionMappingConfig extends Located implements Serializable { - - protected String name; - protected String exceptionClassName; - protected String result; - protected Map params; - - protected ExceptionMappingConfig(String name, String exceptionClassName, String result) { - this.name = name; - this.exceptionClassName = exceptionClassName; - this.result = result; - this.params = new LinkedHashMap<>(); - } - - protected ExceptionMappingConfig(ExceptionMappingConfig target) { - this.name = target.name; - this.exceptionClassName = target.exceptionClassName; - this.result = target.result; - this.params = new LinkedHashMap<>(target.params); - this.location = target.location; - } - - public String getName() { - return name; - } - - public String getExceptionClassName() { - return exceptionClassName; - } - - public String getResult() { - return result; - } - - public Map getParams() { - return params; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (!(o instanceof ExceptionMappingConfig)) { - return false; - } - - final ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) o; - - if ((name != null) ? (!name.equals(exceptionMappingConfig.name)) : (exceptionMappingConfig.name != null)) { - return false; - } - - if ((exceptionClassName != null) ? (!exceptionClassName.equals(exceptionMappingConfig.exceptionClassName)) : (exceptionMappingConfig.exceptionClassName != null)) - { - return false; - } - - if ((result != null) ? (!result.equals(exceptionMappingConfig.result)) : (exceptionMappingConfig.result != null)) - { - return false; - } - - if ((params != null) ? (!params.equals(exceptionMappingConfig.params)) : (exceptionMappingConfig.params != null)) - { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int hashCode; - hashCode = ((name != null) ? name.hashCode() : 0); - hashCode = (29 * hashCode) + ((exceptionClassName != null) ? exceptionClassName.hashCode() : 0); - hashCode = (29 * hashCode) + ((result != null) ? result.hashCode() : 0); - hashCode = (29 * hashCode) + ((params != null) ? params.hashCode() : 0); - - return hashCode; - } - - @Override - public String toString() { - return "ExceptionMappingConfig: [" + name + "] handle [" - + exceptionClassName + "] to result [" + result + "] with params " + params; - } - - /** - * The builder for this object. An instance of this object is the only way to construct a new instance. The - * purpose is to enforce the immutability of the object. The methods are structured in a way to support chaining. - * After setting any values you need, call the {@link #build()} method to create the object. - */ - public static class Builder{ - - protected ExceptionMappingConfig target; - - public Builder(ExceptionMappingConfig toClone) { - target = new ExceptionMappingConfig(toClone); - } - - public Builder(String name, String exceptionClassName, String result) { - target = new ExceptionMappingConfig(name, exceptionClassName, result); - } - - public Builder name(String name) { - target.name = name; - return this; - } - - public Builder exceptionClassName(String name) { - target.exceptionClassName = name; - return this; - } - - public Builder result(String result) { - target.result = result; - return this; - } - - public Builder addParam(String name, String value) { - target.params.put(name, value); - return this; - } - - public Builder addParams(Map params) { - target.params.putAll(params); - return this; - } - - public Builder location(Location loc) { - target.location = loc; - return this; - } - - public ExceptionMappingConfig build() { - embalmTarget(); - ExceptionMappingConfig result = target; - target = new ExceptionMappingConfig(target); - return result; - } - - protected void embalmTarget() { - target.params = Collections.unmodifiableMap(target.params); - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorConfig.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorConfig.java deleted file mode 100644 index 6baa481786..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorConfig.java +++ /dev/null @@ -1,160 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.entities; - -import com.opensymphony.xwork2.util.location.Located; -import com.opensymphony.xwork2.util.location.Location; - -import java.io.Serializable; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - -/** - * Configuration for Interceptors. - * - *

    - * In the xml configuration file this is defined as the interceptors tag. - *

    - * - * @author Mike - */ -public class InterceptorConfig extends Located implements Serializable { - - protected Map params; - protected String className; - protected String name; - - protected InterceptorConfig(String name, String className) { - this.params = new LinkedHashMap<>(); - this.name = name; - this.className = className; - } - - protected InterceptorConfig(InterceptorConfig orig) { - this.name = orig.name; - this.className = orig.className; - this.params = new LinkedHashMap<>(orig.params); - this.location = orig.location; - } - - public String getClassName() { - return className; - } - - public String getName() { - return name; - } - - public Map getParams() { - return params; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (!(o instanceof InterceptorConfig)) { - return false; - } - - final InterceptorConfig interceptorConfig = (InterceptorConfig) o; - - if ((className != null) ? (!className.equals(interceptorConfig.className)) : (interceptorConfig.className != null)) { - return false; - } - - if ((name != null) ? (!name.equals(interceptorConfig.name)) : (interceptorConfig.name != null)) { - return false; - } - - if ((params != null) ? (!params.equals(interceptorConfig.params)) : (interceptorConfig.params != null)) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result; - result = ((name != null) ? name.hashCode() : 0); - result = (29 * result) + ((className != null) ? className.hashCode() : 0); - result = (29 * result) + ((params != null) ? params.hashCode() : 0); - - return result; - } - - @Override - public String toString() { - return "InterceptorConfig: [" + name + "] => [" + className + "] with params " + params; - } - - /** - * The builder for this object. An instance of this object is the only way to construct a new instance. The - * purpose is to enforce the immutability of the object. The methods are structured in a way to support chaining. - * After setting any values you need, call the {@link #build()} method to create the object. - */ - public static final class Builder { - protected InterceptorConfig target; - - public Builder(String name, String className) { - target = new InterceptorConfig(name, className); - } - - public Builder(InterceptorConfig orig) { - target = new InterceptorConfig(orig); - } - - public Builder name(String name) { - target.name = name; - return this; - } - - public Builder className(String name) { - target.className = name; - return this; - } - - public Builder addParam(String name, String value) { - target.params.put(name, value); - return this; - } - - public Builder addParams(Map params) { - target.params.putAll(params); - return this; - } - - public Builder location(Location loc) { - target.location = loc; - return this; - } - - public InterceptorConfig build() { - embalmTarget(); - InterceptorConfig result = target; - target = new InterceptorConfig(target); - return result; - } - - protected void embalmTarget() { - target.params = Collections.unmodifiableMap(target.params); - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorListHolder.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorListHolder.java deleted file mode 100644 index 432311626f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorListHolder.java +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.entities; - -import java.util.List; - -/** - * InterceptorListHolder - * - * @author Jason Carreira - * Created Jun 1, 2003 1:02:48 AM - */ -public interface InterceptorListHolder { - - InterceptorListHolder addInterceptor(InterceptorMapping interceptor); - - InterceptorListHolder addInterceptors(List interceptors); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorLocator.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorLocator.java deleted file mode 100644 index aa74960953..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorLocator.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.opensymphony.xwork2.config.entities; - -/** - * Defines an object that can be used to retrieve interceptor configuration - */ -public interface InterceptorLocator { - - /** - * Gets an interceptor configuration object. - * @param name The interceptor or interceptor stack name - * @return Either an {@link InterceptorConfig} or {@link InterceptorStackConfig} object - */ - Object getInterceptorConfig(String name); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java deleted file mode 100644 index 36ba95c888..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/entities/InterceptorMapping.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.config.entities; - -import com.opensymphony.xwork2.interceptor.Interceptor; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; - -/** - * InterceptorMapping - * - * @author Rainer Hermanns - * @version $Id$ - */ -public class InterceptorMapping implements Serializable { - - private String name; - private Interceptor interceptor; - private final Map params; - - public InterceptorMapping(String name, Interceptor interceptor) { - this(name, interceptor, new HashMap()); - } - - public InterceptorMapping(String name, Interceptor interceptor, Map params) { - this.name = name; - this.interceptor = interceptor; - this.params = params; - } - - public String getName() { - return name; - } - - public Interceptor getInterceptor() { - return interceptor; - } - - public Map getParams() { - return params; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - - final InterceptorMapping that = (InterceptorMapping) o; - - if (name != null ? !name.equals(that.name) : that.name != null) return false; - - return true; - } - - @Override - public int hashCode() { - int result; - result = (name != null ? name.hashCode() : 0); - return result; - } - - @Override - public String toString() { - return "InterceptorMapping: [" + name + "] => [" + interceptor.getClass().getName() + "] with params [" + params + "]" ; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/Parameterizable.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/Parameterizable.java deleted file mode 100644 index 363f502938..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/entities/Parameterizable.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.entities; - -import java.util.Map; - -/** - * - *

    - * Actions implementing Parameterizable will receive a map of the static parameters defined in the action - * configuration. - *

    - * - *

    - * The {@link com.opensymphony.xwork2.interceptor.StaticParametersInterceptor} must be in the action's interceptor - * queue for this to work. - *

    - * - * - * @author Jason Carreira - */ -public interface Parameterizable { - - public void addParam(String name, String value); - - void setParams(Map params); - - Map getParams(); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/ResultConfig.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/ResultConfig.java deleted file mode 100644 index b74ce03dd7..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/entities/ResultConfig.java +++ /dev/null @@ -1,161 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.entities; - -import com.opensymphony.xwork2.util.location.Located; -import com.opensymphony.xwork2.util.location.Location; - -import java.io.Serializable; -import java.util.Collections; -import java.util.LinkedHashMap; -import java.util.Map; - - -/** - * Configuration for Result. - * - *

    - * In the xml configuration file this is defined as the result tag. - *

    - * - * @author Mike - */ -public class ResultConfig extends Located implements Serializable { - - protected Map params; - protected String className; - protected String name; - - protected ResultConfig(String name, String className) { - this.name = name; - this.className = className; - params = new LinkedHashMap<>(); - } - - protected ResultConfig(ResultConfig orig) { - this.params = orig.params; - this.name = orig.name; - this.className = orig.className; - this.location = orig.location; - } - - public String getClassName() { - return className; - } - - public String getName() { - return name; - } - - public Map getParams() { - return params; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (!(o instanceof ResultConfig)) { - return false; - } - - final ResultConfig resultConfig = (ResultConfig) o; - - if ((className != null) ? (!className.equals(resultConfig.className)) : (resultConfig.className != null)) { - return false; - } - - if ((name != null) ? (!name.equals(resultConfig.name)) : (resultConfig.name != null)) { - return false; - } - - if ((params != null) ? (!params.equals(resultConfig.params)) : (resultConfig.params != null)) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result; - result = ((name != null) ? name.hashCode() : 0); - result = (29 * result) + ((className != null) ? className.hashCode() : 0); - result = (29 * result) + ((params != null) ? params.hashCode() : 0); - - return result; - } - - @Override - public String toString() { - return "ResultConfig: [" + name + "] => [" + className + "] with params " + params; - } - - /** - * The builder for this object. An instance of this object is the only way to construct a new instance. The - * purpose is to enforce the immutability of the object. The methods are structured in a way to support chaining. - * After setting any values you need, call the {@link #build()} method to create the object. - */ - public static final class Builder { - protected ResultConfig target; - - public Builder(String name, String className) { - target = new ResultConfig(name, className); - } - - public Builder(ResultConfig orig) { - target = new ResultConfig(orig); - } - - public Builder name(String name) { - target.name = name; - return this; - } - - public Builder className(String name) { - target.className = name; - return this; - } - - public Builder addParam(String name, String value) { - target.params.put(name, value); - return this; - } - - public Builder addParams(Map params) { - target.params.putAll(params); - return this; - } - - public Builder location(Location loc) { - target.location = loc; - return this; - } - - public ResultConfig build() { - embalmTarget(); - ResultConfig result = target; - target = new ResultConfig(target); - return result; - } - - protected void embalmTarget() { - target.params = Collections.unmodifiableMap(target.params); - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/UnknownHandlerConfig.java b/core/src/main/java/com/opensymphony/xwork2/config/entities/UnknownHandlerConfig.java deleted file mode 100644 index 3d6692f0ce..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/entities/UnknownHandlerConfig.java +++ /dev/null @@ -1,43 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.entities; - -import com.opensymphony.xwork2.util.location.Located; -import com.opensymphony.xwork2.util.location.Location; - -public class UnknownHandlerConfig extends Located { - - private String name; - - public UnknownHandlerConfig(String name, Location location) { - this.name = name; - this.location = location; - } - - public String getName() { - return name; - } - - public void setName(String name) { - this.name = name; - } - - @Override - public String toString() { - return "UnknownHandlerConfig: [" + name + "]"; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/entities/package.html b/core/src/main/java/com/opensymphony/xwork2/config/entities/package.html deleted file mode 100644 index d05a357625..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/entities/package.html +++ /dev/null @@ -1,18 +0,0 @@ - - -

    -Configuration entity classes. All objects ending in "Config" are immutable and must be constructed using -their inner "Builder" class. For example, a PackageConfig object can be created via: -

    -
    -    PackageConfig config = new PackageConfig.Builder("myPackage").build();
    -
    -

    - The methods on the builder object are chainable to support constructions like this: -

    -
    -    ResultConfig config = new ResultConfig.Builder("success", "myapp.MyResult")
    -        .addParam("location", "/foo.jsp")
    -        .build();
    -
    - diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/AbstractMatcher.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/AbstractMatcher.java deleted file mode 100644 index 954657f85f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/AbstractMatcher.java +++ /dev/null @@ -1,268 +0,0 @@ -/* - * $Id$ - * - * Copyright 2003,2004 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.impl; - -import com.opensymphony.xwork2.util.PatternMatcher; -import org.apache.commons.lang3.math.NumberUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.Serializable; -import java.util.*; - -/** - *

    Matches patterns against pre-compiled wildcard expressions pulled from - * target objects. It uses the wildcard matcher from the Apache Cocoon - * project. Patterns will be matched in the order they were added. The first - * match wins, so more specific patterns should be defined before less specific - * patterns. - * - * @since 2.1 - */ -public abstract class AbstractMatcher implements Serializable { - /** - *

    The logging instance

    - */ - private static final Logger log = LogManager.getLogger(AbstractMatcher.class); - - /** - *

    Handles all wildcard pattern matching.

    - */ - PatternMatcher wildcard; - - /** - *

    The compiled patterns and their associated target objects

    - */ - List> compiledPatterns = new ArrayList<>(); - ; - - public AbstractMatcher(PatternMatcher helper) { - this.wildcard = (PatternMatcher) helper; - } - - /** - *

    - * Finds and precompiles the wildcard patterns. Patterns will be evaluated - * in the order they were added. Only patterns that actually contain a - * wildcard will be compiled. - *

    - * - *

    - * Patterns can optionally be matched "loosely". When the end of the pattern - * matches \*[^*]\*$ (wildcard, no wildcard, wildcard), if the pattern - * fails, it is also matched as if the last two characters didn't exist. The - * goal is to support the legacy "*!*" syntax, where the "!*" is optional. - *

    - * - * @param name The pattern - * @param target The object to associate with the pattern - * @param looseMatch - * To loosely match wildcards or not - */ - public void addPattern(String name, E target, boolean looseMatch) { - - Object pattern; - - if (!wildcard.isLiteral(name)) { - if (looseMatch && (name.length() > 0) && (name.charAt(0) == '/')) { - name = name.substring(1); - } - - log.debug("Compiling pattern '{}'", name); - - pattern = wildcard.compilePattern(name); - compiledPatterns.add(new Mapping(name, pattern, target)); - - if (looseMatch) { - int lastStar = name.lastIndexOf('*'); - if (lastStar > 1 && lastStar == name.length() - 1) { - if (name.charAt(lastStar - 1) != '*') { - pattern = wildcard.compilePattern(name.substring(0, lastStar - 1)); - compiledPatterns.add(new Mapping(name, pattern, target)); - } - } - } - } - } - - public void freeze() { - compiledPatterns = Collections.unmodifiableList(new ArrayList>()); - } - - /** - *

    Matches the path against the compiled wildcard patterns.

    - * - * @param potentialMatch The portion of the request URI for selecting a config. - * @return The action config if matched, else null - */ - public E match(String potentialMatch) { - E config = null; - - if (compiledPatterns.size() > 0) { - log.debug("Attempting to match '{}' to a wildcard pattern, {} available", potentialMatch, compiledPatterns.size()); - - Map vars = new LinkedHashMap(); - for (Mapping m : compiledPatterns) { - if (wildcard.match(vars, potentialMatch, m.getPattern())) { - log.debug("Value matches pattern '{}'", m.getOriginalPattern()); - config = convert(potentialMatch, m.getTarget(), vars); - break; - } - } - } - - return config; - } - - /** - *

    Clones the target object and its children, replacing various - * properties with the values of the wildcard-matched strings.

    - * - * @param path The requested path - * @param orig The original object - * @param vars A Map of wildcard-matched strings - * @return A cloned object with appropriate properties replaced with - * wildcard-matched values - */ - protected abstract E convert(String path, E orig, Map vars); - - /** - *

    Replaces parameter values

    - * - * @param orig The original parameters with placeholder values - * @param vars A Map of wildcard-matched strings - * - * @return map with replaced parameters - */ - protected Map replaceParameters(Map orig, Map vars) { - Map map = new LinkedHashMap<>(); - - //this will set the group index references, like {1} - for (String key : orig.keySet()) { - map.put(key, convertParam(orig.get(key), vars)); - } - - //the values map will contain entries like name->"Lex Luthor" and 1->"Lex Luthor" - //now add the non-numeric values - for (String key: vars.keySet()) { - if (!NumberUtils.isNumber(key)) { - map.put(key, vars.get(key)); - } - } - - return map; - } - - /** - *

    Inserts into a value wildcard-matched strings where specified - * with the {x} syntax. If a wildcard-matched value isn't found, the - * replacement token is turned into an empty string. - *

    - * - * @param val The value to convert - * @param vars A Map of wildcard-matched strings - * @return The new value - */ - protected String convertParam(String val, Map vars) { - if (val == null) { - return null; - } - - int len = val.length(); - StringBuilder ret = new StringBuilder(); - char c; - String varVal; - for (int x=0; x Stores a compiled wildcard pattern and the object it came - * from.

    - */ - private static class Mapping implements Serializable { - /** - *

    The original pattern.

    - */ - private String original; - - - /** - *

    The compiled pattern.

    - */ - private Object pattern; - - /** - *

    The original object.

    - */ - private E config; - - /** - *

    Contructs a read-only Mapping instance.

    - * - * @param original The original pattern - * @param pattern The compiled pattern - * @param config The original object - */ - public Mapping(String original, Object pattern, E config) { - this.original = original; - this.pattern = pattern; - this.config = config; - } - - /** - *

    Gets the compiled wildcard pattern.

    - * - * @return The compiled pattern - */ - public Object getPattern() { - return this.pattern; - } - - /** - *

    Gets the object that contains the pattern.

    - * - * @return The associated object - */ - public E getTarget() { - return this.config; - } - - /** - *

    Gets the original wildcard pattern.

    - * - * @return The original pattern - */ - public String getOriginalPattern() { - return this.original; - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcher.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcher.java deleted file mode 100644 index 07a8c46a29..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/ActionConfigMatcher.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * $Id$ - * - * Copyright 2003,2004 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.impl; - -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig; -import com.opensymphony.xwork2.config.entities.ResultConfig; -import com.opensymphony.xwork2.util.PatternMatcher; -import org.apache.commons.lang3.StringUtils; - -import java.io.Serializable; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -/** - *

    Matches paths against pre-compiled wildcard expressions pulled from - * action configs. It uses the wildcard matcher from the Apache Cocoon - * project. Patterns will be matched in the order they exist in the - * config file. The first match wins, so more specific patterns should be - * defined before less specific patterns. - */ -public class ActionConfigMatcher extends AbstractMatcher implements Serializable { - - /** - *

    Finds and precompiles the wildcard patterns from the ActionConfig - * "path" attributes. ActionConfig's will be evaluated in the order they - * exist in the config file. Only paths that actually contain a - * wildcard will be compiled.

    - * - *

    Patterns can optionally be matched "loosely". When - * the end of the pattern matches \*[^*]\*$ (wildcard, no wildcard, - * wildcard), if the pattern fails, it is also matched as if the - * last two characters didn't exist. The goal is to support the - * legacy "*!*" syntax, where the "!*" is optional.

    - * - * @param patternMatcher pattern matcher - * @param configs An array of ActionConfig's to process - * @param looseMatch To loosely match wildcards or not - */ - public ActionConfigMatcher(PatternMatcher patternMatcher, - Map configs, - boolean looseMatch) { - super(patternMatcher); - for (String name : configs.keySet()) { - addPattern(name, configs.get(name), looseMatch); - } - } - - /** - *

    Clones the ActionConfig and its children, replacing various - * properties with the values of the wildcard-matched strings.

    - * - * @param path The requested path - * @param orig The original ActionConfig - * @param vars A Map of wildcard-matched strings - * @return A cloned ActionConfig with appropriate properties replaced with - * wildcard-matched values - */ - @Override public ActionConfig convert(String path, ActionConfig orig, - Map vars) { - - String methodName = convertParam(orig.getMethodName(), vars); - - if (StringUtils.isEmpty(methodName)) { - methodName = ActionConfig.DEFAULT_METHOD; - } - - if (!orig.isAllowedMethod(methodName)) { - return null; - } - - String className = convertParam(orig.getClassName(), vars); - String pkgName = convertParam(orig.getPackageName(), vars); - - Map params = replaceParameters(orig.getParams(), vars); - - Map results = new LinkedHashMap<>(); - for (String name : orig.getResults().keySet()) { - ResultConfig result = orig.getResults().get(name); - name = convertParam(name, vars); - ResultConfig r = new ResultConfig.Builder(name, convertParam(result.getClassName(), vars)) - .addParams(replaceParameters(result.getParams(), vars)) - .build(); - results.put(name, r); - } - - List exs = new ArrayList(); - for (ExceptionMappingConfig ex : orig.getExceptionMappings()) { - String name = convertParam(ex.getName(), vars); - String exClassName = convertParam(ex.getExceptionClassName(), vars); - String exResult = convertParam(ex.getResult(), vars); - Map exParams = replaceParameters(ex.getParams(), vars); - ExceptionMappingConfig e = new ExceptionMappingConfig.Builder(name, exClassName, exResult).addParams(exParams).build(); - exs.add(e); - } - - return new ActionConfig.Builder(pkgName, orig.getName(), className) - .methodName(methodName) - .addParams(params) - .addResultConfigs(results) - .setStrictMethodInvocation(orig.isStrictMethodInvocation()) - .addAllowedMethod(orig.getAllowedMethods()) - .addInterceptors(orig.getInterceptors()) - .addExceptionMappings(exs) - .location(orig.getLocation()) - .build(); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java deleted file mode 100644 index c7c5a92775..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/DefaultConfiguration.java +++ /dev/null @@ -1,526 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.impl; - -import com.opensymphony.xwork2.*; -import com.opensymphony.xwork2.config.*; -import com.opensymphony.xwork2.config.entities.*; -import com.opensymphony.xwork2.config.providers.EnvsValueSubstitutor; -import com.opensymphony.xwork2.config.providers.InterceptorBuilder; -import com.opensymphony.xwork2.config.providers.ValueSubstitutor; -import com.opensymphony.xwork2.conversion.*; -import com.opensymphony.xwork2.conversion.impl.*; -import com.opensymphony.xwork2.factory.*; -import com.opensymphony.xwork2.inject.*; -import com.opensymphony.xwork2.ognl.OgnlReflectionProvider; -import com.opensymphony.xwork2.ognl.OgnlUtil; -import com.opensymphony.xwork2.ognl.OgnlValueStackFactory; -import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor; -import com.opensymphony.xwork2.util.*; -import com.opensymphony.xwork2.util.fs.DefaultFileManager; -import com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory; -import com.opensymphony.xwork2.util.location.LocatableProperties; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; -import ognl.PropertyAccessor; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.struts2.StrutsConstants; - -import java.util.*; - - -/** - * DefaultConfiguration - * - * @author Jason Carreira - * Created Feb 24, 2003 7:38:06 AM - */ -public class DefaultConfiguration implements Configuration { - - protected static final Logger LOG = LogManager.getLogger(DefaultConfiguration.class); - - // Programmatic Action Configurations - protected Map packageContexts = new LinkedHashMap<>(); - protected RuntimeConfiguration runtimeConfiguration; - protected Container container; - protected String defaultFrameworkBeanName; - protected Set loadedFileNames = new TreeSet<>(); - protected List unknownHandlerStack; - - - ObjectFactory objectFactory; - - public DefaultConfiguration() { - this(Container.DEFAULT_NAME); - } - - public DefaultConfiguration(String defaultBeanName) { - this.defaultFrameworkBeanName = defaultBeanName; - } - - - public PackageConfig getPackageConfig(String name) { - return packageContexts.get(name); - } - - public List getUnknownHandlerStack() { - return unknownHandlerStack; - } - - public void setUnknownHandlerStack(List unknownHandlerStack) { - this.unknownHandlerStack = unknownHandlerStack; - } - - public Set getPackageConfigNames() { - return packageContexts.keySet(); - } - - public Map getPackageConfigs() { - return packageContexts; - } - - public Set getLoadedFileNames() { - return loadedFileNames; - } - - public RuntimeConfiguration getRuntimeConfiguration() { - return runtimeConfiguration; - } - - /** - * @return the container - */ - public Container getContainer() { - return container; - } - - public void addPackageConfig(String name, PackageConfig packageContext) { - PackageConfig check = packageContexts.get(name); - if (check != null) { - if (check.getLocation() != null && packageContext.getLocation() != null - && check.getLocation().equals(packageContext.getLocation())) { - LOG.debug("The package name '{}' is already been loaded by the same location and could be removed: {}", - name, packageContext.getLocation()); - } else { - throw new ConfigurationException("The package name '" + name - + "' at location "+packageContext.getLocation() - + " is already been used by another package at location " + check.getLocation(), - packageContext); - } - } - packageContexts.put(name, packageContext); - } - - public PackageConfig removePackageConfig(String packageName) { - return packageContexts.remove(packageName); - } - - /** - * Allows the configuration to clean up any resources used - */ - public void destroy() { - packageContexts.clear(); - loadedFileNames.clear(); - } - - public void rebuildRuntimeConfiguration() { - runtimeConfiguration = buildRuntimeConfiguration(); - } - - /** - * Calls the ConfigurationProviderFactory.getConfig() to tell it to reload the configuration and then calls - * buildRuntimeConfiguration(). - * - * @return list of package providers - * - * @throws ConfigurationException in case of any configuration errors - */ - public synchronized List reloadContainer(List providers) throws ConfigurationException { - packageContexts.clear(); - loadedFileNames.clear(); - List packageProviders = new ArrayList<>(); - - ContainerProperties props = new ContainerProperties(); - ContainerBuilder builder = new ContainerBuilder(); - Container bootstrap = createBootstrapContainer(providers); - for (final ContainerProvider containerProvider : providers) - { - bootstrap.inject(containerProvider); - containerProvider.init(this); - containerProvider.register(builder, props); - } - props.setConstants(builder); - - builder.factory(Configuration.class, new Factory() { - public Configuration create(Context context) throws Exception { - return DefaultConfiguration.this; - } - }); - - ActionContext oldContext = ActionContext.getContext(); - try { - // Set the bootstrap container for the purposes of factory creation - - setContext(bootstrap); - container = builder.create(false); - setContext(container); - objectFactory = container.getInstance(ObjectFactory.class); - - // Process the configuration providers first - for (final ContainerProvider containerProvider : providers) - { - if (containerProvider instanceof PackageProvider) { - container.inject(containerProvider); - ((PackageProvider)containerProvider).loadPackages(); - packageProviders.add((PackageProvider)containerProvider); - } - } - - // Then process any package providers from the plugins - Set packageProviderNames = container.getInstanceNames(PackageProvider.class); - for (String name : packageProviderNames) { - PackageProvider provider = container.getInstance(PackageProvider.class, name); - provider.init(this); - provider.loadPackages(); - packageProviders.add(provider); - } - - rebuildRuntimeConfiguration(); - } finally { - if (oldContext == null) { - ActionContext.setContext(null); - } - } - return packageProviders; - } - - protected ActionContext setContext(Container cont) { - ActionContext context = ActionContext.getContext(); - if (context == null) { - ValueStack vs = cont.getInstance(ValueStackFactory.class).createValueStack(); - context = new ActionContext(vs.getContext()); - ActionContext.setContext(context); - } - return context; - } - - protected Container createBootstrapContainer(List providers) { - ContainerBuilder builder = new ContainerBuilder(); - boolean fmFactoryRegistered = false; - for (ContainerProvider provider : providers) { - if (provider instanceof FileManagerProvider) { - provider.register(builder, null); - } - if (provider instanceof FileManagerFactoryProvider) { - provider.register(builder, null); - fmFactoryRegistered = true; - } - } - builder.factory(ObjectFactory.class, Scope.SINGLETON); - builder.factory(ActionFactory.class, DefaultActionFactory.class, Scope.SINGLETON); - builder.factory(ResultFactory.class, DefaultResultFactory.class, Scope.SINGLETON); - builder.factory(InterceptorFactory.class, DefaultInterceptorFactory.class, Scope.SINGLETON); - builder.factory(com.opensymphony.xwork2.factory.ValidatorFactory.class, com.opensymphony.xwork2.factory.DefaultValidatorFactory.class, Scope.SINGLETON); - builder.factory(ConverterFactory.class, DefaultConverterFactory.class, Scope.SINGLETON); - builder.factory(UnknownHandlerFactory.class, DefaultUnknownHandlerFactory.class, Scope.SINGLETON); - - builder.factory(FileManager.class, "system", DefaultFileManager.class, Scope.SINGLETON); - if (!fmFactoryRegistered) { - builder.factory(FileManagerFactory.class, DefaultFileManagerFactory.class, Scope.SINGLETON); - } - builder.factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON); - builder.factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON); - - builder.factory(LocalizedTextProvider.class, DefaultLocalizedTextProvider.class, Scope.SINGLETON); - - builder.factory(XWorkConverter.class, Scope.SINGLETON); - builder.factory(ConversionPropertiesProcessor.class, DefaultConversionPropertiesProcessor.class, Scope.SINGLETON); - builder.factory(ConversionFileProcessor.class, DefaultConversionFileProcessor.class, Scope.SINGLETON); - builder.factory(ConversionAnnotationProcessor.class, DefaultConversionAnnotationProcessor.class, Scope.SINGLETON); - builder.factory(TypeConverterCreator.class, DefaultTypeConverterCreator.class, Scope.SINGLETON); - builder.factory(TypeConverterHolder.class, DefaultTypeConverterHolder.class, Scope.SINGLETON); - - builder.factory(XWorkBasicConverter.class, Scope.SINGLETON); - builder.factory(TypeConverter.class, XWorkConstants.COLLECTION_CONVERTER, CollectionConverter.class, Scope.SINGLETON); - builder.factory(TypeConverter.class, XWorkConstants.ARRAY_CONVERTER, ArrayConverter.class, Scope.SINGLETON); - builder.factory(TypeConverter.class, XWorkConstants.DATE_CONVERTER, DateConverter.class, Scope.SINGLETON); - builder.factory(TypeConverter.class, XWorkConstants.NUMBER_CONVERTER, NumberConverter.class, Scope.SINGLETON); - builder.factory(TypeConverter.class, XWorkConstants.STRING_CONVERTER, StringConverter.class, Scope.SINGLETON); - - builder.factory(TextParser.class, OgnlTextParser.class, Scope.SINGLETON); - builder.factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON); - builder.factory(TextProvider.class, TextProviderSupport.class, Scope.SINGLETON); - builder.factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON); - - builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON); - builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON); - builder.factory(OgnlUtil.class, Scope.SINGLETON); - - builder.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON); - - builder.constant(XWorkConstants.DEV_MODE, "false"); - builder.constant(StrutsConstants.STRUTS_DEVMODE, "false"); - builder.constant(XWorkConstants.LOG_MISSING_PROPERTIES, "false"); - builder.constant(XWorkConstants.ENABLE_OGNL_EVAL_EXPRESSION, "false"); - builder.constant(XWorkConstants.ENABLE_OGNL_EXPRESSION_CACHE, "true"); - builder.constant(XWorkConstants.RELOAD_XML_CONFIGURATION, "false"); - builder.constant(StrutsConstants.STRUTS_I18N_RELOAD, "false"); - - return builder.create(true); - } - - /** - *

    - * This builds the internal runtime configuration used by Xwork for finding and configuring Actions from the - * programmatic configuration data structures. All of the old runtime configuration will be discarded and rebuilt. - *

    - * - *

    - * It basically flattens the data structures to make the information easier to access. It will take - * an {@link ActionConfig} and combine its data with all inherited dast. For example, if the {@link ActionConfig} - * is in a package that contains a global result and it also contains a result, the resulting {@link ActionConfig} - * will have two results. - *

    - * - * @return runtime configuration - * @throws ConfigurationException in case of any configuration errors - */ - protected synchronized RuntimeConfiguration buildRuntimeConfiguration() throws ConfigurationException { - Map> namespaceActionConfigs = new LinkedHashMap<>(); - Map namespaceConfigs = new LinkedHashMap<>(); - - for (PackageConfig packageConfig : packageContexts.values()) { - - if (!packageConfig.isAbstract()) { - String namespace = packageConfig.getNamespace(); - Map configs = namespaceActionConfigs.get(namespace); - - if (configs == null) { - configs = new LinkedHashMap<>(); - } - - Map actionConfigs = packageConfig.getAllActionConfigs(); - - for (Object o : actionConfigs.keySet()) { - String actionName = (String) o; - ActionConfig baseConfig = actionConfigs.get(actionName); - configs.put(actionName, buildFullActionConfig(packageConfig, baseConfig)); - } - - namespaceActionConfigs.put(namespace, configs); - if (packageConfig.getFullDefaultActionRef() != null) { - namespaceConfigs.put(namespace, packageConfig.getFullDefaultActionRef()); - } - } - } - - PatternMatcher matcher = container.getInstance(PatternMatcher.class); - return new RuntimeConfigurationImpl(Collections.unmodifiableMap(namespaceActionConfigs), - Collections.unmodifiableMap(namespaceConfigs), matcher); - } - - private void setDefaultResults(Map results, PackageConfig packageContext) { - String defaultResult = packageContext.getFullDefaultResultType(); - - for (Map.Entry entry : results.entrySet()) { - - if (entry.getValue() == null) { - ResultTypeConfig resultTypeConfig = packageContext.getAllResultTypeConfigs().get(defaultResult); - entry.setValue(new ResultConfig.Builder(null, resultTypeConfig.getClassName()).build()); - } - } - } - - /** - * Builds the full runtime actionconfig with all of the defaults and inheritance - * - * @param packageContext the PackageConfig which holds the base config we're building from - * @param baseConfig the ActionConfig which holds only the configuration specific to itself, without the defaults - * and inheritance - * @return a full ActionConfig for runtime configuration with all of the inherited and default params - * @throws com.opensymphony.xwork2.config.ConfigurationException - * - */ - private ActionConfig buildFullActionConfig(PackageConfig packageContext, ActionConfig baseConfig) throws ConfigurationException { - Map params = new TreeMap<>(baseConfig.getParams()); - Map results = new TreeMap<>(); - - if (!baseConfig.getPackageName().equals(packageContext.getName()) && packageContexts.containsKey(baseConfig.getPackageName())) { - results.putAll(packageContexts.get(baseConfig.getPackageName()).getAllGlobalResults()); - } else { - results.putAll(packageContext.getAllGlobalResults()); - } - - results.putAll(baseConfig.getResults()); - - setDefaultResults(results, packageContext); - - List interceptors = new ArrayList<>(baseConfig.getInterceptors()); - - if (interceptors.size() <= 0) { - String defaultInterceptorRefName = packageContext.getFullDefaultInterceptorRef(); - - if (defaultInterceptorRefName != null) { - interceptors.addAll(InterceptorBuilder.constructInterceptorReference(new PackageConfig.Builder(packageContext), defaultInterceptorRefName, - new LinkedHashMap(), packageContext.getLocation(), objectFactory)); - } - } - - String methodRegex = container.getInstance(String.class, StrutsConstants.STRUTS_SMI_METHOD_REGEX); - if (methodRegex == null) { - methodRegex = ActionConfig.DEFAULT_METHOD_REGEX; - } - - LOG.debug("Using pattern [{}] to match allowed methods when SMI is disabled!", methodRegex); - - return new ActionConfig.Builder(baseConfig) - .addParams(params) - .addResultConfigs(results) - .defaultClassName(packageContext.getDefaultClassRef()) // fill in default if non class has been provided - .interceptors(interceptors) - .setStrictMethodInvocation(packageContext.isStrictMethodInvocation()) - .setDefaultMethodRegex(methodRegex) - .addExceptionMappings(packageContext.getAllExceptionMappingConfigs()) - .build(); - } - - - private static class RuntimeConfigurationImpl implements RuntimeConfiguration { - - private Map> namespaceActionConfigs; - private Map namespaceActionConfigMatchers; - private NamespaceMatcher namespaceMatcher; - private Map namespaceConfigs; - - public RuntimeConfigurationImpl(Map> namespaceActionConfigs, - Map namespaceConfigs, - PatternMatcher matcher) { - this.namespaceActionConfigs = namespaceActionConfigs; - this.namespaceConfigs = namespaceConfigs; - - this.namespaceActionConfigMatchers = new LinkedHashMap<>(); - this.namespaceMatcher = new NamespaceMatcher(matcher, namespaceActionConfigs.keySet()); - - for (String ns : namespaceActionConfigs.keySet()) { - namespaceActionConfigMatchers.put(ns, new ActionConfigMatcher(matcher, namespaceActionConfigs.get(ns), true)); - } - } - - - /** - * Gets the configuration information for an action name, or returns null if the - * name is not recognized. - * - * @param name the name of the action - * @param namespace the namespace for the action or null for the empty namespace, "" - * @return the configuration information for action requested - */ - public ActionConfig getActionConfig(String namespace, String name) { - ActionConfig config = findActionConfigInNamespace(namespace, name); - - // try wildcarded namespaces - if (config == null) { - NamespaceMatch match = namespaceMatcher.match(namespace); - if (match != null) { - config = findActionConfigInNamespace(match.getPattern(), name); - - // If config found, place all the matches found in the namespace processing in the action's parameters - if (config != null) { - config = new ActionConfig.Builder(config) - .addParams(match.getVariables()) - .build(); - } - } - } - - // fail over to empty namespace - if (config == null && StringUtils.isNotBlank(namespace)) { - config = findActionConfigInNamespace("", name); - } - - - return config; - } - - private ActionConfig findActionConfigInNamespace(String namespace, String name) { - ActionConfig config = null; - if (namespace == null) { - namespace = ""; - } - Map actions = namespaceActionConfigs.get(namespace); - if (actions != null) { - config = actions.get(name); - // Check wildcards - if (config == null) { - config = namespaceActionConfigMatchers.get(namespace).match(name); - // fail over to default action - if (config == null) { - String defaultActionRef = namespaceConfigs.get(namespace); - if (defaultActionRef != null) { - config = actions.get(defaultActionRef); - } - } - } - } - return config; - } - - /** - * Gets the configuration settings for every action. - * - * @return a Map of namespace - > Map of ActionConfig objects, with the key being the action name - */ - public Map> getActionConfigs() { - return namespaceActionConfigs; - } - - @Override - public String toString() { - StringBuilder buff = new StringBuilder("RuntimeConfiguration - actions are\n"); - - for (String namespace : namespaceActionConfigs.keySet()) { - Map actionConfigs = namespaceActionConfigs.get(namespace); - - for (String s : actionConfigs.keySet()) { - buff.append(namespace).append("/").append(s).append("\n"); - } - } - - return buff.toString(); - } - } - - class ContainerProperties extends LocatableProperties { - private static final long serialVersionUID = -7320625750836896089L; - - @Override - public Object setProperty(String key, String value) { - String oldValue = getProperty(key); - if (LOG.isInfoEnabled() && oldValue != null && !oldValue.equals(value) && !defaultFrameworkBeanName.equals(oldValue)) { - LOG.info("Overriding property {} - old value: {} new value: {}", key, oldValue, value); - } - return super.setProperty(key, value); - } - - public void setConstants(ContainerBuilder builder) { - for (Object keyobj : keySet()) { - String key = (String)keyobj; - builder.factory(String.class, key, new LocatableConstantFactory<>(getProperty(key), getPropertyLocation(key))); - } - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java deleted file mode 100644 index eb218f8592..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableConstantFactory.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * - */ -package com.opensymphony.xwork2.config.impl; - -import com.opensymphony.xwork2.inject.Context; -import com.opensymphony.xwork2.inject.Factory; -import com.opensymphony.xwork2.util.location.Located; -import com.opensymphony.xwork2.util.location.LocationUtils; - -/** - * Factory that remembers where a constant came from - */ -public class LocatableConstantFactory extends Located implements Factory { - T constant; - public LocatableConstantFactory(T constant, Object location) { - this.constant = constant; - setLocation(LocationUtils.getLocation(location)); - } - - public T create(Context ignored) { - return constant; - } - - @Override - public String toString() { - StringBuilder sb = new StringBuilder(); - sb.append(super.toString()); - sb.append(" defined at "); - sb.append(getLocation().toString()); - return sb.toString(); - } - -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java deleted file mode 100644 index 2f95dfe701..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/LocatableFactory.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.opensymphony.xwork2.config.impl; - -import com.opensymphony.xwork2.inject.Context; -import com.opensymphony.xwork2.inject.Factory; -import com.opensymphony.xwork2.inject.Scope; -import com.opensymphony.xwork2.util.location.Located; -import com.opensymphony.xwork2.util.location.LocationUtils; - -import java.util.LinkedHashMap; - -/** - * Attaches location information to the factory. - */ -public class LocatableFactory extends Located implements Factory { - - - private Class implementation; - private Class type; - private String name; - private Scope scope; - - public LocatableFactory(String name, Class type, Class implementation, Scope scope, Object location) { - this.implementation = implementation; - this.type = type; - this.name = name; - this.scope = scope; - setLocation(LocationUtils.getLocation(location)); - } - - @SuppressWarnings("unchecked") - public T create(Context context) { - Object obj = context.getContainer().inject(implementation); - return (T) obj; - } - - @Override - public String toString() { - String fields = new LinkedHashMap() { - { - put("type", type); - put("name", name); - put("implementation", implementation); - put("scope", scope); - } - }.toString(); - StringBuilder sb = new StringBuilder(fields); - sb.append(super.toString()); - sb.append(" defined at "); - sb.append(getLocation().toString()); - return sb.toString(); - } -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java deleted file mode 100644 index 120d3f9ae2..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/MockConfiguration.java +++ /dev/null @@ -1,117 +0,0 @@ -/* - * Copyright 2002-2003,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.impl; - -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.config.*; -import com.opensymphony.xwork2.config.entities.PackageConfig; -import com.opensymphony.xwork2.config.entities.UnknownHandlerConfig; -import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.ContainerBuilder; -import com.opensymphony.xwork2.inject.Scope; -import com.opensymphony.xwork2.util.location.LocatableProperties; -import org.apache.struts2.StrutsConstants; - -import java.util.*; - - -/** - * Simple configuration used for unit testing - */ -public class MockConfiguration implements Configuration { - - private Map packages = new HashMap<>(); - private Set loadedFiles = new HashSet<>(); - private Container container; - protected List unknownHandlerStack; - private ContainerBuilder builder; - - public MockConfiguration() { - builder = new ContainerBuilder(); - } - - public void selfRegister() { - //this cannot be done in the constructor, as it causes an infinite loop - builder.factory(Configuration.class, MockConfiguration.class, Scope.SINGLETON); - LocatableProperties props = new LocatableProperties(); - new XWorkConfigurationProvider().register(builder, props); - builder.constant(XWorkConstants.DEV_MODE, "false"); - builder.constant(XWorkConstants.RELOAD_XML_CONFIGURATION, "true"); - builder.constant(XWorkConstants.ENABLE_OGNL_EXPRESSION_CACHE, "true"); - builder.constant(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, "false"); - container = builder.create(true); - } - - public PackageConfig getPackageConfig(String name) { - return packages.get(name); - } - - public Set getPackageConfigNames() { - return packages.keySet(); - } - - public Map getPackageConfigs() { - return packages; - } - - public RuntimeConfiguration getRuntimeConfiguration() { - throw new UnsupportedOperationException(); - } - - public void addPackageConfig(String name, PackageConfig packageContext) { - packages.put(name, packageContext); - } - - public void buildRuntimeConfiguration() { - throw new UnsupportedOperationException(); - } - - public void destroy() { - throw new UnsupportedOperationException(); - } - - public void rebuildRuntimeConfiguration() { - throw new UnsupportedOperationException(); - } - - public PackageConfig removePackageConfig(String name) { - return packages.remove(name); - } - - public Container getContainer() { - return container; - } - - public Set getLoadedFileNames() { - return loadedFiles; - } - - public List reloadContainer( - List containerProviders) - throws ConfigurationException { - throw new UnsupportedOperationException(); - } - - public List getUnknownHandlerStack() { - return unknownHandlerStack; - } - - public void setUnknownHandlerStack(List unknownHandlerStack) { - this.unknownHandlerStack = unknownHandlerStack; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java deleted file mode 100644 index ce2ae705a4..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatch.java +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.impl; - -import java.util.Map; - -/** - * Represents a match from a namespace pattern matching. - * - * @since 2.1 - */ -public class NamespaceMatch { - private String pattern; - private Map variables; - - public NamespaceMatch(String pattern, Map variables) { - this.pattern = pattern; - this.variables = variables; - } - - /** - * @return The pattern that was matched - */ - public String getPattern() { - return pattern; - } - - /** - * @return The variables containing the matched values - */ - public Map getVariables() { - return variables; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java b/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java deleted file mode 100644 index 6fa9ec39a7..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/NamespaceMatcher.java +++ /dev/null @@ -1,51 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.impl; - -import com.opensymphony.xwork2.util.PatternMatcher; - -import java.util.Map; -import java.util.Set; - -/** - * Matches namespace strings against a wildcard pattern matcher - * - * @since 2.1 - */ -public class NamespaceMatcher extends AbstractMatcher { - public NamespaceMatcher(PatternMatcher patternMatcher, - Set namespaces) { - super(patternMatcher); - for (String name : namespaces) { - if (!patternMatcher.isLiteral(name)) { - addPattern(name, new NamespaceMatch(name, null), false); - } - } - } - - @Override - protected NamespaceMatch convert(String path, NamespaceMatch orig, Map vars) { - /*Map origVars = (Map)vars; - Map map = new HashMap(); - for (Map.Entry entry : origVars.entrySet()) { - if (entry.getKey().length() == 1) { - map.put("ns"+entry.getKey(), entry.getValue()); - } - } - */ - return new NamespaceMatch(orig.getPattern(), vars); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html b/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html deleted file mode 100644 index cdfed5f83e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/impl/package.html +++ /dev/null @@ -1 +0,0 @@ -Configuration implementation classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/config/package.html b/core/src/main/java/com/opensymphony/xwork2/config/package.html deleted file mode 100644 index a3de692bc7..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/package.html +++ /dev/null @@ -1 +0,0 @@ -Configuration core classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/CycleDetector.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/CycleDetector.java deleted file mode 100644 index 0e45f5dadd..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/CycleDetector.java +++ /dev/null @@ -1,59 +0,0 @@ -package com.opensymphony.xwork2.config.providers; - -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -public class CycleDetector { - private DirectedGraph graph; - private Map marks; - private List verticesInCycles; - - private enum Status { MARKED, COMPLETE }; - - public CycleDetector(DirectedGraph graph) { - this.graph = graph; - marks = new HashMap<>(); - verticesInCycles = new ArrayList<>(); - } - - public boolean containsCycle() { - for (T v : graph) { - if (!marks.containsKey(v)) { - if (mark(v)) { - // return true; - } - } - } - // return false; - return !verticesInCycles.isEmpty(); - } - - private boolean mark(T vertex) { - /* - * return statements commented out for fail slow behavior detect all nodes in cycles instead of just the first one - */ - List localCycles = new ArrayList(); - marks.put(vertex, Status.MARKED); - for (T u : graph.edgesFrom(vertex)) { - if (marks.get(u) == Status.MARKED) { - localCycles.add(vertex); - // return true; - } else if (!marks.containsKey(u)) { - if (mark(u)) { - localCycles.add(vertex); - // return true; - } - } - } - marks.put(vertex, Status.COMPLETE); - // return false; - verticesInCycles.addAll(localCycles); - return !localCycles.isEmpty(); - } - - public List getVerticesInCycles() { - return verticesInCycles; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/EnvsValueSubstitutor.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/EnvsValueSubstitutor.java deleted file mode 100644 index b4b1086e94..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/EnvsValueSubstitutor.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.providers; - -import org.apache.commons.lang3.text.StrSubstitutor; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -public class EnvsValueSubstitutor implements ValueSubstitutor { - - private static final Logger LOG = LogManager.getLogger(EnvsValueSubstitutor.class); - - protected StrSubstitutor strSubstitutor; - - public EnvsValueSubstitutor() { - strSubstitutor = new StrSubstitutor(System.getenv()); - strSubstitutor.setVariablePrefix("${env."); - strSubstitutor.setVariableSuffix('}'); - strSubstitutor.setValueDelimiter(":"); - } - - @Override - public String substitute(String value) { - LOG.debug("Substituting value {} with proper System variable or environment variable", value); - - String substituted = StrSubstitutor.replaceSystemProperties(value); - return strSubstitutor.replace(substituted); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java deleted file mode 100644 index 8044c1a7cb..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/InterceptorBuilder.java +++ /dev/null @@ -1,215 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.providers; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.entities.InterceptorConfig; -import com.opensymphony.xwork2.config.entities.InterceptorLocator; -import com.opensymphony.xwork2.config.entities.InterceptorMapping; -import com.opensymphony.xwork2.config.entities.InterceptorStackConfig; -import com.opensymphony.xwork2.interceptor.Interceptor; -import com.opensymphony.xwork2.util.location.Location; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.message.ParameterizedMessage; - -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - - -/** - * Builds a list of interceptors referenced by the refName in the supplied PackageConfig. - * - * @author Mike - * @author Rainer Hermanns - * @author tmjee - */ -public class InterceptorBuilder { - - private static final Logger LOG = LogManager.getLogger(InterceptorBuilder.class); - - /** - * Builds a list of interceptors referenced by the refName in the supplied PackageConfig (InterceptorMapping object). - * - * @param interceptorLocator interceptor locator - * @param refName reference name - * @param refParams reference parameters - * @param location location - * @param objectFactory object factory - * @return list of interceptors referenced by the refName in the supplied PackageConfig (InterceptorMapping object). - * @throws ConfigurationException in case of any configuration errors - */ - public static List constructInterceptorReference(InterceptorLocator interceptorLocator, - String refName, Map refParams, Location location, ObjectFactory objectFactory) throws ConfigurationException { - Object referencedConfig = interceptorLocator.getInterceptorConfig(refName); - List result = new ArrayList<>(); - - if (referencedConfig == null) { - throw new ConfigurationException("Unable to find interceptor class referenced by ref-name " + refName, location); - } else { - if (referencedConfig instanceof InterceptorConfig) { - InterceptorConfig config = (InterceptorConfig) referencedConfig; - Interceptor inter; - try { - inter = objectFactory.buildInterceptor(config, refParams); - result.add(new InterceptorMapping(refName, inter, refParams)); - } catch (ConfigurationException ex) { - LOG.warn(new ParameterizedMessage("Unable to load config class {} at {} probably due to a missing jar, which might be fine if you never plan to use the {} interceptor", - config.getClassName(), ex.getLocation(), config.getName()), ex); - } - - } else if (referencedConfig instanceof InterceptorStackConfig) { - InterceptorStackConfig stackConfig = (InterceptorStackConfig) referencedConfig; - - if ((refParams != null) && (refParams.size() > 0)) { - result = constructParameterizedInterceptorReferences(interceptorLocator, stackConfig, refParams, objectFactory); - } else { - result.addAll(stackConfig.getInterceptors()); - } - - } else { - LOG.error("Got unexpected type for interceptor {}. Got {}", refName, referencedConfig); - } - } - - return result; - } - - /** - * Builds a list of interceptors referenced by the refName in the supplied PackageConfig overriding the properties - * of the referenced interceptor with refParams. - * - * @param interceptorLocator interceptor locator - * @param stackConfig interceptor stack configuration - * @param refParams The overridden interceptor properties - * @return list of interceptors referenced by the refName in the supplied PackageConfig overridden with refParams. - */ - private static List constructParameterizedInterceptorReferences( - InterceptorLocator interceptorLocator, InterceptorStackConfig stackConfig, Map refParams, - ObjectFactory objectFactory) { - List result; - Map> params = new LinkedHashMap<>(); - - /* - * We strip - * - * - * someValue - * anotherValue - * - * - * down to map - * interceptor1 -> [param1 -> someValue, param2 -> anotherValue] - * - * or - * - * someValue - * anotherValue - * - * - * down to map - * interceptorStack1 -> [interceptor1.param1 -> someValue, interceptor1.param2 -> anotherValue] - * - */ - for (String key : refParams.keySet()) { - String value = refParams.get(key); - - try { - String name = key.substring(0, key.indexOf('.')); - key = key.substring(key.indexOf('.') + 1); - - Map map; - if (params.containsKey(name)) { - map = params.get(name); - } else { - map = new LinkedHashMap<>(); - } - - map.put(key, value); - params.put(name, map); - - } catch (Exception e) { - LOG.warn("No interceptor found for name = {}", key); - } - } - - result = new ArrayList<>(stackConfig.getInterceptors()); - - for (String key : params.keySet()) { - - Map map = params.get(key); - - - Object interceptorCfgObj = interceptorLocator.getInterceptorConfig(key); - - /* - * Now we attempt to separate out param that refers to Interceptor - * and Interceptor stack, eg. - * - * - * someValue - * ... - * - * - * vs - * - * - * someValue - * ... - * - */ - if (interceptorCfgObj instanceof InterceptorConfig) { // interceptor-ref param refer to an interceptor - InterceptorConfig cfg = (InterceptorConfig) interceptorCfgObj; - Interceptor interceptor = objectFactory.buildInterceptor(cfg, map); - - InterceptorMapping mapping = new InterceptorMapping(key, interceptor); - if (result.contains(mapping)) { - for (int index = 0; index < result.size(); index++) { - InterceptorMapping interceptorMapping = result.get(index); - if (interceptorMapping.getName().equals(key)) { - LOG.debug("Overriding interceptor config [{}] with new mapping {} using new params {}", key, interceptorMapping, map); - result.set(index, mapping); - } - } - } else { - result.add(mapping); - } - } else - if (interceptorCfgObj instanceof InterceptorStackConfig) { // interceptor-ref param refer to an interceptor stack - - // If its an interceptor-stack, we call this method recursively until, - // all the params (eg. interceptorStack1.interceptor1.param etc.) - // are resolved down to a specific interceptor. - - InterceptorStackConfig stackCfg = (InterceptorStackConfig) interceptorCfgObj; - List tmpResult = constructParameterizedInterceptorReferences(interceptorLocator, stackCfg, map, objectFactory); - for (InterceptorMapping tmpInterceptorMapping : tmpResult) { - if (result.contains(tmpInterceptorMapping)) { - int index = result.indexOf(tmpInterceptorMapping); - result.set(index, tmpInterceptorMapping); - } else { - result.add(tmpInterceptorMapping); - } - } - } - } - - return result; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/ValueSubstitutor.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/ValueSubstitutor.java deleted file mode 100644 index ceedb6a58b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/ValueSubstitutor.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.providers; - -/** - * @since Apache Struts 2.5.6 - */ -public interface ValueSubstitutor { - - String substitute(String value); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java deleted file mode 100644 index 5c912e1fce..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/XWorkConfigurationProvider.java +++ /dev/null @@ -1,215 +0,0 @@ -package com.opensymphony.xwork2.config.providers; - -import com.opensymphony.xwork2.ActionProxyFactory; -import com.opensymphony.xwork2.DefaultActionProxyFactory; -import com.opensymphony.xwork2.DefaultLocaleProviderFactory; -import com.opensymphony.xwork2.LocaleProviderFactory; -import com.opensymphony.xwork2.TextProviderFactory; -import com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory; -import com.opensymphony.xwork2.factory.UnknownHandlerFactory; -import com.opensymphony.xwork2.ognl.accessor.HttpParametersPropertyAccessor; -import com.opensymphony.xwork2.ognl.accessor.ParameterPropertyAccessor; -import com.opensymphony.xwork2.security.AcceptedPatternsChecker; -import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker; -import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker; -import com.opensymphony.xwork2.DefaultLocaleProvider; -import com.opensymphony.xwork2.DefaultTextProvider; -import com.opensymphony.xwork2.DefaultUnknownHandlerManager; -import com.opensymphony.xwork2.security.ExcludedPatternsChecker; -import com.opensymphony.xwork2.FileManager; -import com.opensymphony.xwork2.FileManagerFactory; -import com.opensymphony.xwork2.LocaleProvider; -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.TextProvider; -import com.opensymphony.xwork2.TextProviderSupport; -import com.opensymphony.xwork2.UnknownHandlerManager; -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.ConfigurationProvider; -import com.opensymphony.xwork2.conversion.ConversionAnnotationProcessor; -import com.opensymphony.xwork2.conversion.ConversionFileProcessor; -import com.opensymphony.xwork2.conversion.ConversionPropertiesProcessor; -import com.opensymphony.xwork2.conversion.NullHandler; -import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer; -import com.opensymphony.xwork2.conversion.TypeConverterCreator; -import com.opensymphony.xwork2.conversion.TypeConverterHolder; -import com.opensymphony.xwork2.conversion.impl.ArrayConverter; -import com.opensymphony.xwork2.conversion.impl.CollectionConverter; -import com.opensymphony.xwork2.conversion.impl.DateConverter; -import com.opensymphony.xwork2.conversion.impl.DefaultConversionAnnotationProcessor; -import com.opensymphony.xwork2.conversion.impl.DefaultConversionFileProcessor; -import com.opensymphony.xwork2.conversion.impl.DefaultConversionPropertiesProcessor; -import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer; -import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverterCreator; -import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverterHolder; -import com.opensymphony.xwork2.conversion.impl.InstantiatingNullHandler; -import com.opensymphony.xwork2.conversion.impl.NumberConverter; -import com.opensymphony.xwork2.conversion.impl.StringConverter; -import com.opensymphony.xwork2.conversion.impl.XWorkBasicConverter; -import com.opensymphony.xwork2.conversion.impl.XWorkConverter; -import com.opensymphony.xwork2.factory.ActionFactory; -import com.opensymphony.xwork2.factory.ConverterFactory; -import com.opensymphony.xwork2.factory.DefaultActionFactory; -import com.opensymphony.xwork2.factory.DefaultConverterFactory; -import com.opensymphony.xwork2.factory.DefaultInterceptorFactory; -import com.opensymphony.xwork2.factory.DefaultResultFactory; -import com.opensymphony.xwork2.factory.InterceptorFactory; -import com.opensymphony.xwork2.factory.ResultFactory; -import com.opensymphony.xwork2.inject.ContainerBuilder; -import com.opensymphony.xwork2.inject.Scope; -import com.opensymphony.xwork2.ognl.ObjectProxy; -import com.opensymphony.xwork2.ognl.OgnlReflectionContextFactory; -import com.opensymphony.xwork2.ognl.OgnlReflectionProvider; -import com.opensymphony.xwork2.ognl.OgnlUtil; -import com.opensymphony.xwork2.ognl.OgnlValueStackFactory; -import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor; -import com.opensymphony.xwork2.ognl.accessor.ObjectAccessor; -import com.opensymphony.xwork2.ognl.accessor.ObjectProxyPropertyAccessor; -import com.opensymphony.xwork2.ognl.accessor.XWorkCollectionPropertyAccessor; -import com.opensymphony.xwork2.ognl.accessor.XWorkEnumerationAccessor; -import com.opensymphony.xwork2.ognl.accessor.XWorkIteratorPropertyAccessor; -import com.opensymphony.xwork2.ognl.accessor.XWorkListPropertyAccessor; -import com.opensymphony.xwork2.ognl.accessor.XWorkMapPropertyAccessor; -import com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor; -import com.opensymphony.xwork2.util.CompoundRoot; -import com.opensymphony.xwork2.LocalizedTextProvider; -import com.opensymphony.xwork2.util.DefaultLocalizedTextProvider; -import com.opensymphony.xwork2.util.OgnlTextParser; -import com.opensymphony.xwork2.util.PatternMatcher; -import com.opensymphony.xwork2.util.TextParser; -import com.opensymphony.xwork2.util.ValueStackFactory; -import com.opensymphony.xwork2.util.WildcardHelper; -import com.opensymphony.xwork2.util.fs.DefaultFileManager; -import com.opensymphony.xwork2.util.fs.DefaultFileManagerFactory; -import com.opensymphony.xwork2.util.location.LocatableProperties; -import com.opensymphony.xwork2.util.reflection.ReflectionContextFactory; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; -import com.opensymphony.xwork2.validator.ActionValidatorManager; -import com.opensymphony.xwork2.validator.AnnotationActionValidatorManager; -import com.opensymphony.xwork2.validator.DefaultActionValidatorManager; -import com.opensymphony.xwork2.validator.DefaultValidatorFactory; -import com.opensymphony.xwork2.validator.DefaultValidatorFileParser; -import com.opensymphony.xwork2.validator.ValidatorFactory; -import com.opensymphony.xwork2.validator.ValidatorFileParser; -import ognl.MethodAccessor; -import ognl.PropertyAccessor; -import org.apache.struts2.StrutsConstants; -import org.apache.struts2.dispatcher.HttpParameters; -import org.apache.struts2.dispatcher.Parameter; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Enumeration; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -public class XWorkConfigurationProvider implements ConfigurationProvider { - - public void destroy() { - } - - public void init(Configuration configuration) throws ConfigurationException { - } - - public void loadPackages() throws ConfigurationException { - } - - public boolean needsReload() { - return false; - } - - public void register(ContainerBuilder builder, LocatableProperties props) - throws ConfigurationException { - - builder - .factory(ObjectFactory.class) - .factory(ActionFactory.class, DefaultActionFactory.class) - .factory(ResultFactory.class, DefaultResultFactory.class) - .factory(InterceptorFactory.class, DefaultInterceptorFactory.class) - .factory(com.opensymphony.xwork2.factory.ValidatorFactory.class, com.opensymphony.xwork2.factory.DefaultValidatorFactory.class) - .factory(ConverterFactory.class, DefaultConverterFactory.class) - .factory(UnknownHandlerFactory.class, DefaultUnknownHandlerFactory.class) - - .factory(ActionProxyFactory.class, DefaultActionProxyFactory.class, Scope.SINGLETON) - .factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON) - - .factory(XWorkConverter.class, Scope.SINGLETON) - .factory(XWorkBasicConverter.class, Scope.SINGLETON) - .factory(ConversionPropertiesProcessor.class, DefaultConversionPropertiesProcessor.class, Scope.SINGLETON) - .factory(ConversionFileProcessor.class, DefaultConversionFileProcessor.class, Scope.SINGLETON) - .factory(ConversionAnnotationProcessor.class, DefaultConversionAnnotationProcessor.class, Scope.SINGLETON) - .factory(TypeConverterCreator.class, DefaultTypeConverterCreator.class, Scope.SINGLETON) - .factory(TypeConverterHolder.class, DefaultTypeConverterHolder.class, Scope.SINGLETON) - - .factory(FileManager.class, "system", DefaultFileManager.class, Scope.SINGLETON) - .factory(FileManagerFactory.class, DefaultFileManagerFactory.class, Scope.SINGLETON) - .factory(ValueStackFactory.class, OgnlValueStackFactory.class, Scope.SINGLETON) - .factory(ValidatorFactory.class, DefaultValidatorFactory.class, Scope.SINGLETON) - .factory(ValidatorFileParser.class, DefaultValidatorFileParser.class, Scope.SINGLETON) - .factory(PatternMatcher.class, WildcardHelper.class, Scope.SINGLETON) - .factory(ReflectionProvider.class, OgnlReflectionProvider.class, Scope.SINGLETON) - .factory(ReflectionContextFactory.class, OgnlReflectionContextFactory.class, Scope.SINGLETON) - - .factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Object.class.getName(), ObjectAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Iterator.class.getName(), XWorkIteratorPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Enumeration.class.getName(), XWorkEnumerationAccessor.class, Scope.SINGLETON) - - .factory(UnknownHandlerManager.class, DefaultUnknownHandlerManager.class, Scope.SINGLETON) - - // silly workarounds for ognl since there is no way to flush its caches - .factory(PropertyAccessor.class, List.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, ArrayList.class.getName(), XWorkListPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, HashSet.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Set.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, HashMap.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Map.class.getName(), XWorkMapPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Collection.class.getName(), XWorkCollectionPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, ObjectProxy.class.getName(), ObjectProxyPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, HttpParameters.class.getName(), HttpParametersPropertyAccessor.class, Scope.SINGLETON) - .factory(PropertyAccessor.class, Parameter.class.getName(), ParameterPropertyAccessor.class, Scope.SINGLETON) - - .factory(MethodAccessor.class, Object.class.getName(), XWorkMethodAccessor.class, Scope.SINGLETON) - .factory(MethodAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON) - - .factory(TextParser.class, OgnlTextParser.class, Scope.SINGLETON) - - .factory(NullHandler.class, Object.class.getName(), InstantiatingNullHandler.class, Scope.SINGLETON) - .factory(ActionValidatorManager.class, AnnotationActionValidatorManager.class, Scope.SINGLETON) - .factory(ActionValidatorManager.class, "no-annotations", DefaultActionValidatorManager.class, Scope.SINGLETON) - - .factory(TextProviderFactory.class, Scope.SINGLETON) - .factory(LocalizedTextProvider.class, DefaultLocalizedTextProvider.class, Scope.SINGLETON) - .factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON) - .factory(TextProvider.class, TextProviderSupport.class, Scope.SINGLETON) - - .factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON) - .factory(OgnlUtil.class, Scope.SINGLETON) - .factory(CollectionConverter.class, Scope.SINGLETON) - .factory(ArrayConverter.class, Scope.SINGLETON) - .factory(DateConverter.class, Scope.SINGLETON) - .factory(NumberConverter.class, Scope.SINGLETON) - .factory(StringConverter.class, Scope.SINGLETON) - - .factory(ExcludedPatternsChecker.class, DefaultExcludedPatternsChecker.class, Scope.PROTOTYPE) - .factory(AcceptedPatternsChecker.class, DefaultAcceptedPatternsChecker.class, Scope.PROTOTYPE) - - .factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON) - ; - - props.setProperty(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, Boolean.FALSE.toString()); - props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, Boolean.FALSE.toString()); - props.setProperty(StrutsConstants.STRUTS_DEVMODE, Boolean.FALSE.toString()); - props.setProperty(XWorkConstants.DEV_MODE, Boolean.FALSE.toString()); - props.setProperty(XWorkConstants.LOG_MISSING_PROPERTIES, Boolean.FALSE.toString()); - props.setProperty(XWorkConstants.ENABLE_OGNL_EXPRESSION_CACHE, Boolean.TRUE.toString()); - props.setProperty(XWorkConstants.ENABLE_OGNL_EVAL_EXPRESSION, Boolean.FALSE.toString()); - props.setProperty(XWorkConstants.RELOAD_XML_CONFIGURATION, Boolean.FALSE.toString()); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java deleted file mode 100644 index 0e2c45107e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/XmlConfigurationProvider.java +++ /dev/null @@ -1,1162 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.config.providers; - -import com.opensymphony.xwork2.Action; -import com.opensymphony.xwork2.FileManager; -import com.opensymphony.xwork2.FileManagerFactory; -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.XWorkException; -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.ConfigurationProvider; -import com.opensymphony.xwork2.config.ConfigurationUtil; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig; -import com.opensymphony.xwork2.config.entities.InterceptorConfig; -import com.opensymphony.xwork2.config.entities.InterceptorMapping; -import com.opensymphony.xwork2.config.entities.InterceptorStackConfig; -import com.opensymphony.xwork2.config.entities.PackageConfig; -import com.opensymphony.xwork2.config.entities.ResultConfig; -import com.opensymphony.xwork2.config.entities.ResultTypeConfig; -import com.opensymphony.xwork2.config.entities.UnknownHandlerConfig; -import com.opensymphony.xwork2.config.impl.LocatableFactory; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.ContainerBuilder; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.inject.Scope; -import com.opensymphony.xwork2.util.ClassLoaderUtil; -import com.opensymphony.xwork2.util.ClassPathFinder; -import com.opensymphony.xwork2.util.DomHelper; -import com.opensymphony.xwork2.util.TextParseUtil; -import com.opensymphony.xwork2.util.location.LocatableProperties; -import com.opensymphony.xwork2.util.location.Location; -import com.opensymphony.xwork2.util.location.LocationUtils; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.w3c.dom.Document; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.xml.sax.InputSource; - -import java.io.IOException; -import java.io.InputStream; -import java.lang.reflect.Modifier; -import java.net.URL; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Set; -import java.util.Vector; - - -/** - * Looks in the classpath for an XML file, "xwork.xml" by default, - * and uses it for the XWork configuration. - * - * @author tmjee - * @author Rainer Hermanns - * @author Neo - * @version $Revision$ - */ -public class XmlConfigurationProvider implements ConfigurationProvider { - - private static final Logger LOG = LogManager.getLogger(XmlConfigurationProvider.class); - - private List documents; - private Set includedFileNames; - private String configFileName; - private ObjectFactory objectFactory; - - private Set loadedFileUrls = new HashSet<>(); - private boolean errorIfMissing; - private Map dtdMappings; - private Configuration configuration; - private boolean throwExceptionOnDuplicateBeans = true; - private Map declaredPackages = new HashMap<>(); - - private FileManager fileManager; - private ValueSubstitutor valueSubstitutor; - - public XmlConfigurationProvider() { - this("xwork.xml", true); - } - - public XmlConfigurationProvider(String filename) { - this(filename, true); - } - - public XmlConfigurationProvider(String filename, boolean errorIfMissing) { - this.configFileName = filename; - this.errorIfMissing = errorIfMissing; - - Map mappings = new HashMap<>(); - mappings.put("-//Apache Struts//XWork 2.5//EN", "xwork-2.5.dtd"); - mappings.put("-//Apache Struts//XWork 2.3//EN", "xwork-2.3.dtd"); - mappings.put("-//Apache Struts//XWork 2.1.3//EN", "xwork-2.1.3.dtd"); - mappings.put("-//Apache Struts//XWork 2.1//EN", "xwork-2.1.dtd"); - mappings.put("-//Apache Struts//XWork 2.0//EN", "xwork-2.0.dtd"); - mappings.put("-//Apache Struts//XWork 1.1.1//EN", "xwork-1.1.1.dtd"); - mappings.put("-//Apache Struts//XWork 1.1//EN", "xwork-1.1.dtd"); - mappings.put("-//Apache Struts//XWork 1.0//EN", "xwork-1.0.dtd"); - setDtdMappings(mappings); - } - - public void setThrowExceptionOnDuplicateBeans(boolean val) { - this.throwExceptionOnDuplicateBeans = val; - } - - public void setDtdMappings(Map mappings) { - this.dtdMappings = Collections.unmodifiableMap(mappings); - } - - @Inject - public void setObjectFactory(ObjectFactory objectFactory) { - this.objectFactory = objectFactory; - } - - @Inject - public void setFileManagerFactory(FileManagerFactory fileManagerFactory) { - this.fileManager = fileManagerFactory.getFileManager(); - } - - @Inject(required = false) - public void setValueSubstitutor(ValueSubstitutor valueSubstitutor) { - this.valueSubstitutor = valueSubstitutor; - } - - /** - * Returns an unmodifiable map of DTD mappings - * - * @return map of DTD mappings - */ - public Map getDtdMappings() { - return dtdMappings; - } - - public void init(Configuration configuration) { - this.configuration = configuration; - this.includedFileNames = configuration.getLoadedFileNames(); - loadDocuments(configFileName); - } - - public void destroy() { - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (!(o instanceof XmlConfigurationProvider)) { - return false; - } - - final XmlConfigurationProvider xmlConfigurationProvider = (XmlConfigurationProvider) o; - - if ((configFileName != null) ? (!configFileName.equals(xmlConfigurationProvider.configFileName)) : (xmlConfigurationProvider.configFileName != null)) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - return ((configFileName != null) ? configFileName.hashCode() : 0); - } - - private void loadDocuments(String configFileName) { - try { - loadedFileUrls.clear(); - documents = loadConfigurationFiles(configFileName, null); - } catch (ConfigurationException e) { - throw e; - } catch (Exception e) { - throw new ConfigurationException("Error loading configuration file " + configFileName, e); - } - } - - public void register(ContainerBuilder containerBuilder, LocatableProperties props) throws ConfigurationException { - LOG.trace("Parsing configuration file [{}]", configFileName); - Map loadedBeans = new HashMap<>(); - for (Document doc : documents) { - Element rootElement = doc.getDocumentElement(); - NodeList children = rootElement.getChildNodes(); - int childSize = children.getLength(); - - for (int i = 0; i < childSize; i++) { - Node childNode = children.item(i); - - if (childNode instanceof Element) { - Element child = (Element) childNode; - - final String nodeName = child.getNodeName(); - - if ("bean".equals(nodeName)) { - String type = child.getAttribute("type"); - String name = child.getAttribute("name"); - String impl = child.getAttribute("class"); - String onlyStatic = child.getAttribute("static"); - String scopeStr = child.getAttribute("scope"); - boolean optional = "true".equals(child.getAttribute("optional")); - Scope scope = Scope.SINGLETON; - if ("prototype".equals(scopeStr)) { - scope = Scope.PROTOTYPE; - } else if ("request".equals(scopeStr)) { - scope = Scope.REQUEST; - } else if ("session".equals(scopeStr)) { - scope = Scope.SESSION; - } else if ("singleton".equals(scopeStr)) { - scope = Scope.SINGLETON; - } else if ("thread".equals(scopeStr)) { - scope = Scope.THREAD; - } - - if (StringUtils.isEmpty(name)) { - name = Container.DEFAULT_NAME; - } - - try { - Class classImpl = ClassLoaderUtil.loadClass(impl, getClass()); - Class classType = classImpl; - if (StringUtils.isNotEmpty(type)) { - classType = ClassLoaderUtil.loadClass(type, getClass()); - } - if ("true".equals(onlyStatic)) { - // Force loading of class to detect no class def found exceptions - classImpl.getDeclaredClasses(); - containerBuilder.injectStatics(classImpl); - } else { - if (containerBuilder.contains(classType, name)) { - Location loc = LocationUtils.getLocation(loadedBeans.get(classType.getName() + name)); - if (throwExceptionOnDuplicateBeans) { - throw new ConfigurationException("Bean type " + classType + " with the name " + - name + " has already been loaded by " + loc, child); - } - } - - // Force loading of class to detect no class def found exceptions - classImpl.getDeclaredConstructors(); - - LOG.debug("Loaded type: {} name: {} impl: {}", type, name, impl); - containerBuilder.factory(classType, name, new LocatableFactory(name, classType, classImpl, scope, childNode), scope); - } - loadedBeans.put(classType.getName() + name, child); - } catch (Throwable ex) { - if (!optional) { - throw new ConfigurationException("Unable to load bean: type:" + type + " class:" + impl, ex, childNode); - } else { - LOG.debug("Unable to load optional class: {}", impl); - } - } - } else if ("constant".equals(nodeName)) { - String name = child.getAttribute("name"); - String value = child.getAttribute("value"); - - if (valueSubstitutor != null) { - LOG.debug("Substituting value [{}] using [{}]", value, valueSubstitutor.getClass().getName()); - value = valueSubstitutor.substitute(value); - } - - props.setProperty(name, value, childNode); - } else if (nodeName.equals("unknown-handler-stack")) { - List unknownHandlerStack = new ArrayList(); - NodeList unknownHandlers = child.getElementsByTagName("unknown-handler-ref"); - int unknownHandlersSize = unknownHandlers.getLength(); - - for (int k = 0; k < unknownHandlersSize; k++) { - Element unknownHandler = (Element) unknownHandlers.item(k); - Location location = LocationUtils.getLocation(unknownHandler); - unknownHandlerStack.add(new UnknownHandlerConfig(unknownHandler.getAttribute("name"), location)); - } - - if (!unknownHandlerStack.isEmpty()) - configuration.setUnknownHandlerStack(unknownHandlerStack); - } - } - } - } - } - - public void loadPackages() throws ConfigurationException { - List reloads = new ArrayList(); - verifyPackageStructure(); - - for (Document doc : documents) { - Element rootElement = doc.getDocumentElement(); - NodeList children = rootElement.getChildNodes(); - int childSize = children.getLength(); - - for (int i = 0; i < childSize; i++) { - Node childNode = children.item(i); - - if (childNode instanceof Element) { - Element child = (Element) childNode; - - final String nodeName = child.getNodeName(); - - if ("package".equals(nodeName)) { - PackageConfig cfg = addPackage(child); - if (cfg.isNeedsRefresh()) { - reloads.add(child); - } - } - } - } - loadExtraConfiguration(doc); - } - - if (reloads.size() > 0) { - reloadRequiredPackages(reloads); - } - - for (Document doc : documents) { - loadExtraConfiguration(doc); - } - - documents.clear(); - declaredPackages.clear(); - configuration = null; - } - - private void verifyPackageStructure() { - DirectedGraph graph = new DirectedGraph<>(); - - for (Document doc : documents) { - Element rootElement = doc.getDocumentElement(); - NodeList children = rootElement.getChildNodes(); - int childSize = children.getLength(); - for (int i = 0; i < childSize; i++) { - Node childNode = children.item(i); - if (childNode instanceof Element) { - Element child = (Element) childNode; - - final String nodeName = child.getNodeName(); - - if ("package".equals(nodeName)) { - String packageName = child.getAttribute("name"); - declaredPackages.put(packageName, child); - graph.addNode(packageName); - - String extendsAttribute = child.getAttribute("extends"); - List parents = ConfigurationUtil.buildParentListFromString(extendsAttribute); - for (String parent : parents) { - graph.addNode(parent); - graph.addEdge(packageName, parent); - } - } - } - } - } - - CycleDetector detector = new CycleDetector<>(graph); - if (detector.containsCycle()) { - StringBuilder builder = new StringBuilder("The following packages participate in cycles:"); - for (String packageName : detector.getVerticesInCycles()) { - builder.append(" "); - builder.append(packageName); - } - throw new ConfigurationException(builder.toString()); - } - } - - private void reloadRequiredPackages(List reloads) { - if (reloads.size() > 0) { - List result = new ArrayList<>(); - for (Element pkg : reloads) { - PackageConfig cfg = addPackage(pkg); - if (cfg.isNeedsRefresh()) { - result.add(pkg); - } - } - if ((result.size() > 0) && (result.size() != reloads.size())) { - reloadRequiredPackages(result); - return; - } - - // Print out error messages for all misconfigured inheritance packages - if (result.size() > 0) { - for (Element rp : result) { - String parent = rp.getAttribute("extends"); - if (parent != null) { - List parents = ConfigurationUtil.buildParentsFromString(configuration, parent); - if (parents != null && parents.size() <= 0) { - LOG.error("Unable to find parent packages {}", parent); - } - } - } - } - } - } - - /** - * Tells whether the ConfigurationProvider should reload its configuration. This method should only be called - * if ConfigurationManager.isReloadingConfigs() is true. - * - * @return true if the file has been changed since the last time we read it - */ - public boolean needsReload() { - - for (String url : loadedFileUrls) { - if (fileManager.fileNeedsReloading(url)) { - return true; - } - } - return false; - } - - protected void addAction(Element actionElement, PackageConfig.Builder packageContext) throws ConfigurationException { - String name = actionElement.getAttribute("name"); - String className = actionElement.getAttribute("class"); - //methodName should be null if it's not set - String methodName = StringUtils.trimToNull(actionElement.getAttribute("method")); - Location location = DomHelper.getLocationObject(actionElement); - - if (location == null) { - LOG.warn("Location null for {}", className); - } - - // if there isn't a class name specified for an then try to - // use the default-class-ref from the - if (StringUtils.isEmpty(className)) { - // if there is a package default-class-ref use that, otherwise use action support - /* if (StringUtils.isNotEmpty(packageContext.getDefaultClassRef())) { - className = packageContext.getDefaultClassRef(); - } else { - className = ActionSupport.class.getName(); - }*/ - - } else { - if (!verifyAction(className, name, location)) { - LOG.error("Unable to verify action [{}] with class [{}], from [{}]", name, className, location); - return; - } - } - - Map results; - try { - results = buildResults(actionElement, packageContext); - } catch (ConfigurationException e) { - throw new ConfigurationException("Error building results for action " + name + " in namespace " + packageContext.getNamespace(), e, actionElement); - } - - List interceptorList = buildInterceptorList(actionElement, packageContext); - - List exceptionMappings = buildExceptionMappings(actionElement, packageContext); - - Set allowedMethods = buildAllowedMethods(actionElement, packageContext); - - ActionConfig actionConfig = new ActionConfig.Builder(packageContext.getName(), name, className) - .methodName(methodName) - .addResultConfigs(results) - .addInterceptors(interceptorList) - .addExceptionMappings(exceptionMappings) - .addParams(XmlHelper.getParams(actionElement)) - .setStrictMethodInvocation(packageContext.isStrictMethodInvocation()) - .addAllowedMethod(allowedMethods) - .location(location) - .build(); - packageContext.addActionConfig(name, actionConfig); - - LOG.debug("Loaded {}{} in '{}' package: {}", - StringUtils.isNotEmpty(packageContext.getNamespace()) ? (packageContext.getNamespace() + "/") : "", - name, packageContext.getName(), actionConfig); - } - - protected boolean verifyAction(String className, String name, Location loc) { - if (className.contains("{")) { - LOG.debug("Action class [{}] contains a wildcard replacement value, so it can't be verified", className); - return true; - } - try { - if (objectFactory.isNoArgConstructorRequired()) { - Class clazz = objectFactory.getClassInstance(className); - if (!Modifier.isPublic(clazz.getModifiers())) { - throw new ConfigurationException("Action class [" + className + "] is not public", loc); - } - clazz.getConstructor(new Class[]{}); - } - } catch (ClassNotFoundException e) { - LOG.debug("Class not found for action [{}]", className, e); - throw new ConfigurationException("Action class [" + className + "] not found", loc); - } catch (NoSuchMethodException e) { - LOG.debug("No constructor found for action [{}]", className, e); - throw new ConfigurationException("Action class [" + className + "] does not have a public no-arg constructor", e, loc); - } catch (RuntimeException ex) { - // Probably not a big deal, like request or session-scoped Spring beans that need a real request - LOG.info("Unable to verify action class [{}] exists at initialization", className); - LOG.debug("Action verification cause", ex); - } catch (Exception ex) { - // Default to failing fast - LOG.debug("Unable to verify action class [{}]", className, ex); - throw new ConfigurationException(ex, loc); - } - return true; - } - - /** - * Create a PackageConfig from an XML element representing it. - * - * @param packageElement the given XML element - * @return the package config - * @throws ConfigurationException in case of configuration errors - */ - protected PackageConfig addPackage(Element packageElement) throws ConfigurationException { - String packageName = packageElement.getAttribute("name"); - PackageConfig packageConfig = configuration.getPackageConfig(packageName); - if (packageConfig != null) { - LOG.debug("Package [{}] already loaded, skipping re-loading it and using existing PackageConfig [{}]", packageName, packageConfig); - return packageConfig; - } - - PackageConfig.Builder newPackage = buildPackageContext(packageElement); - - if (newPackage.isNeedsRefresh()) { - return newPackage.build(); - } - - LOG.debug("Loaded {}", newPackage); - - // add result types (and default result) to this package - addResultTypes(newPackage, packageElement); - - // load the interceptors and interceptor stacks for this package - loadInterceptors(newPackage, packageElement); - - // load the default interceptor reference for this package - loadDefaultInterceptorRef(newPackage, packageElement); - - // load the default class ref for this package - loadDefaultClassRef(newPackage, packageElement); - - // load the global result list for this package - loadGlobalResults(newPackage, packageElement); - - loadGlobalAllowedMethods(newPackage, packageElement); - - // load the global exception handler list for this package - loadGlobalExceptionMappings(newPackage, packageElement); - - // get actions - NodeList actionList = packageElement.getElementsByTagName("action"); - - for (int i = 0; i < actionList.getLength(); i++) { - Element actionElement = (Element) actionList.item(i); - addAction(actionElement, newPackage); - } - - // load the default action reference for this package - loadDefaultActionRef(newPackage, packageElement); - - PackageConfig cfg = newPackage.build(); - configuration.addPackageConfig(cfg.getName(), cfg); - return cfg; - } - - protected void addResultTypes(PackageConfig.Builder packageContext, Element element) { - NodeList resultTypeList = element.getElementsByTagName("result-type"); - - for (int i = 0; i < resultTypeList.getLength(); i++) { - Element resultTypeElement = (Element) resultTypeList.item(i); - String name = resultTypeElement.getAttribute("name"); - String className = resultTypeElement.getAttribute("class"); - String def = resultTypeElement.getAttribute("default"); - - Location loc = DomHelper.getLocationObject(resultTypeElement); - - Class clazz = verifyResultType(className, loc); - if (clazz != null) { - String paramName = null; - try { - paramName = (String) clazz.getField("DEFAULT_PARAM").get(null); - } catch (Throwable t) { - LOG.debug("The result type [{}] doesn't have a default param [DEFAULT_PARAM] defined!", className, t); - } - ResultTypeConfig.Builder resultType = new ResultTypeConfig.Builder(name, className).defaultResultParam(paramName) - .location(DomHelper.getLocationObject(resultTypeElement)); - - Map params = XmlHelper.getParams(resultTypeElement); - - if (!params.isEmpty()) { - resultType.addParams(params); - } - packageContext.addResultTypeConfig(resultType.build()); - - // set the default result type - if (BooleanUtils.toBoolean(def)) { - packageContext.defaultResultType(name); - } - } - } - } - - protected Class verifyResultType(String className, Location loc) { - try { - return objectFactory.getClassInstance(className); - } catch (ClassNotFoundException | NoClassDefFoundError e) { - LOG.warn("Result class [{}] doesn't exist ({}) at {}, ignoring", className, e.getClass().getSimpleName(), loc, e); - } - - return null; - } - - protected List buildInterceptorList(Element element, PackageConfig.Builder context) throws ConfigurationException { - List interceptorList = new ArrayList<>(); - NodeList interceptorRefList = element.getElementsByTagName("interceptor-ref"); - - for (int i = 0; i < interceptorRefList.getLength(); i++) { - Element interceptorRefElement = (Element) interceptorRefList.item(i); - - if (interceptorRefElement.getParentNode().equals(element) || interceptorRefElement.getParentNode().getNodeName().equals(element.getNodeName())) { - List interceptors = lookupInterceptorReference(context, interceptorRefElement); - interceptorList.addAll(interceptors); - } - } - - return interceptorList; - } - - /** - *

    - * This method builds a package context by looking for the parents of this new package. - *

    - * - *

    - * If no parents are found, it will return a root package. - *

    - * - * @param packageElement the package element - * - * @return the package config builder - */ - protected PackageConfig.Builder buildPackageContext(Element packageElement) { - String parent = packageElement.getAttribute("extends"); - String abstractVal = packageElement.getAttribute("abstract"); - boolean isAbstract = Boolean.parseBoolean(abstractVal); - String name = StringUtils.defaultString(packageElement.getAttribute("name")); - String namespace = StringUtils.defaultString(packageElement.getAttribute("namespace")); - - // Strict DMI is enabled by default, it can disabled by user - boolean strictDMI = true; - if (packageElement.hasAttribute("strict-method-invocation")) { - strictDMI = Boolean.parseBoolean(packageElement.getAttribute("strict-method-invocation")); - } - - PackageConfig.Builder cfg = new PackageConfig.Builder(name) - .namespace(namespace) - .isAbstract(isAbstract) - .strictMethodInvocation(strictDMI) - .location(DomHelper.getLocationObject(packageElement)); - - if (StringUtils.isNotEmpty(StringUtils.defaultString(parent))) { // has parents, let's look it up - List parents = new ArrayList<>(); - for (String parentPackageName : ConfigurationUtil.buildParentListFromString(parent)) { - if (configuration.getPackageConfigNames().contains(parentPackageName)) { - parents.add(configuration.getPackageConfig(parentPackageName)); - } else if (declaredPackages.containsKey(parentPackageName)) { - if (configuration.getPackageConfig(parentPackageName) == null) { - addPackage(declaredPackages.get(parentPackageName)); - } - parents.add(configuration.getPackageConfig(parentPackageName)); - } else { - throw new ConfigurationException("Parent package is not defined: " + parentPackageName); - } - - } - - if (parents.size() <= 0) { - cfg.needsRefresh(true); - } else { - cfg.addParents(parents); - } - } - - return cfg; - } - - /** - * Build a map of ResultConfig objects from below a given XML element. - * - * @param element the given XML element - * @param packageContext the package context - * - * @return map of result config objects - */ - protected Map buildResults(Element element, PackageConfig.Builder packageContext) { - NodeList resultEls = element.getElementsByTagName("result"); - - Map results = new LinkedHashMap<>(); - - for (int i = 0; i < resultEls.getLength(); i++) { - Element resultElement = (Element) resultEls.item(i); - - if (resultElement.getParentNode().equals(element) || resultElement.getParentNode().getNodeName().equals(element.getNodeName())) { - String resultName = resultElement.getAttribute("name"); - String resultType = resultElement.getAttribute("type"); - - // if you don't specify a name on , it defaults to "success" - if (StringUtils.isEmpty(resultName)) { - resultName = Action.SUCCESS; - } - - // there is no result type, so let's inherit from the parent package - if (StringUtils.isEmpty(resultType)) { - resultType = packageContext.getFullDefaultResultType(); - - // now check if there is a result type now - if (StringUtils.isEmpty(resultType)) { - // uh-oh, we have a problem - throw new ConfigurationException("No result type specified for result named '" - + resultName + "', perhaps the parent package does not specify the result type?", resultElement); - } - } - - - ResultTypeConfig config = packageContext.getResultType(resultType); - - if (config == null) { - throw new ConfigurationException("There is no result type defined for type '" + resultType - + "' mapped with name '" + resultName + "'." - + " Did you mean '" + guessResultType(resultType) + "'?", resultElement); - } - - String resultClass = config.getClassName(); - - // invalid result type specified in result definition - if (resultClass == null) { - throw new ConfigurationException("Result type '" + resultType + "' is invalid"); - } - - Map resultParams = XmlHelper.getParams(resultElement); - - if (resultParams.size() == 0) // maybe we just have a body - therefore a default parameter - { - // if something then we add a parameter of 'something' as this is the most used result param - if (resultElement.getChildNodes().getLength() >= 1) { - resultParams = new LinkedHashMap<>(); - - String paramName = config.getDefaultResultParam(); - if (paramName != null) { - StringBuilder paramValue = new StringBuilder(); - for (int j = 0; j < resultElement.getChildNodes().getLength(); j++) { - if (resultElement.getChildNodes().item(j).getNodeType() == Node.TEXT_NODE) { - String val = resultElement.getChildNodes().item(j).getNodeValue(); - if (val != null) { - paramValue.append(val); - } - } - } - String val = paramValue.toString().trim(); - if (val.length() > 0) { - resultParams.put(paramName, val); - } - } else { - LOG.debug("No default parameter defined for result [{}] of type [{}] ", config.getName(), config.getClassName()); - } - } - } - - // create new param map, so that the result param can override the config param - Map params = new LinkedHashMap(); - Map configParams = config.getParams(); - if (configParams != null) { - params.putAll(configParams); - } - params.putAll(resultParams); - - Set resultNamesSet = TextParseUtil.commaDelimitedStringToSet(resultName); - if (resultNamesSet.isEmpty()) { - resultNamesSet.add(resultName); - } - - for (String name : resultNamesSet) { - ResultConfig resultConfig = new ResultConfig.Builder(name, resultClass) - .addParams(params) - .location(DomHelper.getLocationObject(element)) - .build(); - results.put(resultConfig.getName(), resultConfig); - } - } - } - - return results; - } - - protected String guessResultType(String type) { - StringBuilder sb = null; - if (type != null) { - sb = new StringBuilder(); - boolean capNext = false; - for (int x=0; x buildExceptionMappings(Element element, PackageConfig.Builder packageContext) { - NodeList exceptionMappingEls = element.getElementsByTagName("exception-mapping"); - - List exceptionMappings = new ArrayList<>(); - - for (int i = 0; i < exceptionMappingEls.getLength(); i++) { - Element ehElement = (Element) exceptionMappingEls.item(i); - - if (ehElement.getParentNode().equals(element) || ehElement.getParentNode().getNodeName().equals(element.getNodeName())) { - String emName = ehElement.getAttribute("name"); - String exceptionClassName = ehElement.getAttribute("exception"); - String exceptionResult = ehElement.getAttribute("result"); - - Map params = XmlHelper.getParams(ehElement); - - if (StringUtils.isEmpty(emName)) { - emName = exceptionResult; - } - - ExceptionMappingConfig ehConfig = new ExceptionMappingConfig.Builder(emName, exceptionClassName, exceptionResult) - .addParams(params) - .location(DomHelper.getLocationObject(ehElement)) - .build(); - exceptionMappings.add(ehConfig); - } - } - - return exceptionMappings; - } - - protected Set buildAllowedMethods(Element element, PackageConfig.Builder packageContext) { - NodeList allowedMethodsEls = element.getElementsByTagName("allowed-methods"); - - Set allowedMethods; - if (allowedMethodsEls.getLength() > 0) { - // user defined 'allowed-methods' so used them whatever Strict DMI was enabled or not - allowedMethods = new HashSet<>(packageContext.getGlobalAllowedMethods()); - - if (allowedMethodsEls.getLength() > 0) { - Node n = allowedMethodsEls.item(0).getFirstChild(); - if (n != null) { - String s = n.getNodeValue().trim(); - if (s.length() > 0) { - allowedMethods.addAll(TextParseUtil.commaDelimitedStringToSet(s)); - } - } - } - } else if (packageContext.isStrictMethodInvocation()) { - // user enabled Strict DMI but didn't defined action specific 'allowed-methods' so we use 'global-allowed-methods' only - allowedMethods = new HashSet<>(packageContext.getGlobalAllowedMethods()); - } else { - // Strict DMI is disabled so any method can be called - allowedMethods = new HashSet<>(); - allowedMethods.add(ActionConfig.WILDCARD); - } - - LOG.debug("Collected allowed methods: {}", allowedMethods); - - return Collections.unmodifiableSet(allowedMethods); - } - - protected void loadDefaultInterceptorRef(PackageConfig.Builder packageContext, Element element) { - NodeList resultTypeList = element.getElementsByTagName("default-interceptor-ref"); - - if (resultTypeList.getLength() > 0) { - Element defaultRefElement = (Element) resultTypeList.item(0); - packageContext.defaultInterceptorRef(defaultRefElement.getAttribute("name")); - } - } - - protected void loadDefaultActionRef(PackageConfig.Builder packageContext, Element element) { - NodeList resultTypeList = element.getElementsByTagName("default-action-ref"); - - if (resultTypeList.getLength() > 0) { - Element defaultRefElement = (Element) resultTypeList.item(0); - packageContext.defaultActionRef(defaultRefElement.getAttribute("name")); - } - } - - /** - * Load all of the global results for this package from the XML element. - * - * @param packageContext the package context - * @param packageElement the given XML element - */ - protected void loadGlobalResults(PackageConfig.Builder packageContext, Element packageElement) { - NodeList globalResultList = packageElement.getElementsByTagName("global-results"); - - if (globalResultList.getLength() > 0) { - Element globalResultElement = (Element) globalResultList.item(0); - Map results = buildResults(globalResultElement, packageContext); - packageContext.addGlobalResultConfigs(results); - } - } - - protected void loadGlobalAllowedMethods(PackageConfig.Builder packageContext, Element packageElement) { - NodeList globalAllowedMethodsElms = packageElement.getElementsByTagName("global-allowed-methods"); - - if (globalAllowedMethodsElms.getLength() > 0) { - Set globalAllowedMethods = new HashSet<>(); - Node n = globalAllowedMethodsElms.item(0).getFirstChild(); - if (n != null) { - String s = n.getNodeValue().trim(); - if (s.length() > 0) { - globalAllowedMethods = TextParseUtil.commaDelimitedStringToSet(s); - } - } - packageContext.addGlobalAllowedMethods(globalAllowedMethods); - } - } - - protected void loadDefaultClassRef(PackageConfig.Builder packageContext, Element element) { - NodeList defaultClassRefList = element.getElementsByTagName("default-class-ref"); - if (defaultClassRefList.getLength() > 0) { - Element defaultClassRefElement = (Element) defaultClassRefList.item(0); - packageContext.defaultClassRef(defaultClassRefElement.getAttribute("class")); - } - } - - /** - * Load all of the global results for this package from the XML element. - * - * @param packageContext the package context - * @param packageElement the given XML element - */ - protected void loadGlobalExceptionMappings(PackageConfig.Builder packageContext, Element packageElement) { - NodeList globalExceptionMappingList = packageElement.getElementsByTagName("global-exception-mappings"); - - if (globalExceptionMappingList.getLength() > 0) { - Element globalExceptionMappingElement = (Element) globalExceptionMappingList.item(0); - List exceptionMappings = buildExceptionMappings(globalExceptionMappingElement, packageContext); - packageContext.addGlobalExceptionMappingConfigs(exceptionMappings); - } - } - - protected InterceptorStackConfig loadInterceptorStack(Element element, PackageConfig.Builder context) throws ConfigurationException { - String name = element.getAttribute("name"); - - InterceptorStackConfig.Builder config = new InterceptorStackConfig.Builder(name) - .location(DomHelper.getLocationObject(element)); - NodeList interceptorRefList = element.getElementsByTagName("interceptor-ref"); - - for (int j = 0; j < interceptorRefList.getLength(); j++) { - Element interceptorRefElement = (Element) interceptorRefList.item(j); - List interceptors = lookupInterceptorReference(context, interceptorRefElement); - config.addInterceptors(interceptors); - } - - return config.build(); - } - - protected void loadInterceptorStacks(Element element, PackageConfig.Builder context) throws ConfigurationException { - NodeList interceptorStackList = element.getElementsByTagName("interceptor-stack"); - - for (int i = 0; i < interceptorStackList.getLength(); i++) { - Element interceptorStackElement = (Element) interceptorStackList.item(i); - - InterceptorStackConfig config = loadInterceptorStack(interceptorStackElement, context); - - context.addInterceptorStackConfig(config); - } - } - - protected void loadInterceptors(PackageConfig.Builder context, Element element) throws ConfigurationException { - NodeList interceptorList = element.getElementsByTagName("interceptor"); - - for (int i = 0; i < interceptorList.getLength(); i++) { - Element interceptorElement = (Element) interceptorList.item(i); - String name = interceptorElement.getAttribute("name"); - String className = interceptorElement.getAttribute("class"); - - Map params = XmlHelper.getParams(interceptorElement); - InterceptorConfig config = new InterceptorConfig.Builder(name, className) - .addParams(params) - .location(DomHelper.getLocationObject(interceptorElement)) - .build(); - - context.addInterceptorConfig(config); - } - - loadInterceptorStacks(element, context); - } - - private List loadConfigurationFiles(String fileName, Element includeElement) { - List docs = new ArrayList<>(); - List finalDocs = new ArrayList<>(); - if (!includedFileNames.contains(fileName)) { - LOG.debug("Loading action configurations from: {}", fileName); - - includedFileNames.add(fileName); - - Iterator urls = null; - InputStream is = null; - - IOException ioException = null; - try { - urls = getConfigurationUrls(fileName); - } catch (IOException ex) { - ioException = ex; - } - - if (urls == null || !urls.hasNext()) { - if (errorIfMissing) { - throw new ConfigurationException("Could not open files of the name " + fileName, ioException); - } else { - LOG.trace("Unable to locate configuration files of the name {}, skipping", fileName); - return docs; - } - } - - URL url = null; - while (urls.hasNext()) { - try { - url = urls.next(); - is = fileManager.loadFile(url); - - InputSource in = new InputSource(is); - - in.setSystemId(url.toString()); - - docs.add(DomHelper.parse(in, dtdMappings)); - loadedFileUrls.add(url.toString()); - } catch (XWorkException e) { - if (includeElement != null) { - throw new ConfigurationException("Unable to load " + url, e, includeElement); - } else { - throw new ConfigurationException("Unable to load " + url, e); - } - } catch (Exception e) { - throw new ConfigurationException("Caught exception while loading file " + fileName, e, includeElement); - } finally { - if (is != null) { - try { - is.close(); - } catch (IOException e) { - LOG.error("Unable to close input stream", e); - } - } - } - } - - //sort the documents, according to the "order" attribute - Collections.sort(docs, new Comparator() { - public int compare(Document doc1, Document doc2) { - return XmlHelper.getLoadOrder(doc1).compareTo(XmlHelper.getLoadOrder(doc2)); - } - }); - - for (Document doc : docs) { - Element rootElement = doc.getDocumentElement(); - NodeList children = rootElement.getChildNodes(); - int childSize = children.getLength(); - - for (int i = 0; i < childSize; i++) { - Node childNode = children.item(i); - - if (childNode instanceof Element) { - Element child = (Element) childNode; - - final String nodeName = child.getNodeName(); - - if ("include".equals(nodeName)) { - String includeFileName = child.getAttribute("file"); - if (includeFileName.indexOf('*') != -1) { - // handleWildCardIncludes(includeFileName, docs, child); - ClassPathFinder wildcardFinder = new ClassPathFinder(); - wildcardFinder.setPattern(includeFileName); - Vector wildcardMatches = wildcardFinder.findMatches(); - for (String match : wildcardMatches) { - finalDocs.addAll(loadConfigurationFiles(match, child)); - } - } else { - finalDocs.addAll(loadConfigurationFiles(includeFileName, child)); - } - } - } - } - finalDocs.add(doc); - } - - LOG.debug("Loaded action configuration from: {}", fileName); - } - return finalDocs; - } - - protected Iterator getConfigurationUrls(String fileName) throws IOException { - return ClassLoaderUtil.getResources(fileName, XmlConfigurationProvider.class, false); - } - - /** - * Allows subclasses to load extra information from the document - * - * @param doc The configuration document - */ - protected void loadExtraConfiguration(Document doc) { - // no op - } - - /** - * Looks up the Interceptor Class from the interceptor-ref name and creates an instance, which is added to the - * provided List, or, if this is a ref to a stack, it adds the Interceptor instances from the List to this stack. - * - * @param context The PackageConfig to lookup the interceptor from - * @param interceptorRefElement Element to pull interceptor ref data from - * @return A list of Interceptor objects - * @throws ConfigurationException in case of configuration errors - */ - private List lookupInterceptorReference(PackageConfig.Builder context, Element interceptorRefElement) throws ConfigurationException { - String refName = interceptorRefElement.getAttribute("name"); - Map refParams = XmlHelper.getParams(interceptorRefElement); - - Location loc = LocationUtils.getLocation(interceptorRefElement); - return InterceptorBuilder.constructInterceptorReference(context, refName, refParams, loc, objectFactory); - } - - List getDocuments() { - return documents; - } - - @Override - public String toString() { - return "XmlConfigurationProvider{" + - "configFileName='" + configFileName + '\'' + - '}'; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/config/providers/package.html b/core/src/main/java/com/opensymphony/xwork2/config/providers/package.html deleted file mode 100644 index 946fc4ef8a..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/config/providers/package.html +++ /dev/null @@ -1 +0,0 @@ -Configuration provider classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionAnnotationProcessor.java b/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionAnnotationProcessor.java deleted file mode 100644 index 159f8d524e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionAnnotationProcessor.java +++ /dev/null @@ -1,23 +0,0 @@ -package com.opensymphony.xwork2.conversion; - -import com.opensymphony.xwork2.conversion.annotations.TypeConversion; - -import java.util.Map; - -/** - * Used to process {@link com.opensymphony.xwork2.conversion.annotations.TypeConversion} - * annotation to read defined Converters - */ -public interface ConversionAnnotationProcessor { - - /** - * Process annotation and build {@link TypeConverter} base on provided annotation - * and assigning it under given key - * - * @param mapping keeps converters per given key - * @param tc annotation which keeps information about converter - * @param key key under which converter should be registered - */ - void process(Map mapping, TypeConversion tc, String key); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionFileProcessor.java b/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionFileProcessor.java deleted file mode 100644 index 0fc0124276..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionFileProcessor.java +++ /dev/null @@ -1,19 +0,0 @@ -package com.opensymphony.xwork2.conversion; - -import java.util.Map; - -/** - * Used to process <clazz>-conversion.properties file to read defined Converters - */ -public interface ConversionFileProcessor { - - /** - * Process conversion file to create mapping for key (property, type) and corresponding converter - * - * @param mapping keeps converters per given key - * @param clazz class which should be converted by the converter - * @param converterFilename to read converters from - */ - void process(Map mapping, Class clazz, String converterFilename); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionPropertiesProcessor.java b/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionPropertiesProcessor.java deleted file mode 100644 index 8d0bab841b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/ConversionPropertiesProcessor.java +++ /dev/null @@ -1,22 +0,0 @@ -package com.opensymphony.xwork2.conversion; - -/** - * Used to read converters from Properties file - */ -public interface ConversionPropertiesProcessor { - - /** - * Process given property to load converters as not required (Properties file doesn't have to exist) - * - * @param propsName Properties file name - */ - void process(String propsName); - - /** - * Process given property to load converters as required (Properties file must exist) - * - * @param propsName Properties file name - */ - void processRequired(String propsName); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/NullHandler.java b/core/src/main/java/com/opensymphony/xwork2/conversion/NullHandler.java deleted file mode 100644 index 9edfda52b4..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/NullHandler.java +++ /dev/null @@ -1,69 +0,0 @@ -//-------------------------------------------------------------------------- -//Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard -//All rights reserved. -// -//Redistribution and use in source and binary forms, with or without -//modification, are permitted provided that the following conditions are -//met: -// -//Redistributions of source code must retain the above copyright notice, -//this list of conditions and the following disclaimer. -//Redistributions in binary form must reproduce the above copyright -//notice, this list of conditions and the following disclaimer in the -//documentation and/or other materials provided with the distribution. -//Neither the name of the Drew Davidson nor the names of its contributors -//may be used to endorse or promote products derived from this software -//without specific prior written permission. -// -//THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -//"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -//LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -//FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -//COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -//INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -//BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -//OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -//AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -//OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -//THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -//DAMAGE. -//-------------------------------------------------------------------------- -package com.opensymphony.xwork2.conversion; - -import java.util.Map; - -/** - *

    - * Interface for handling null results from Chains. - * Object has the opportunity to substitute an object for the - * null and continue. - *

    - * - * @author Luke Blanshard (blanshlu@netscape.net) - * @author Drew Davidson (drew@ognl.org) - */ -public interface NullHandler -{ - /** - * Method called on target returned null. - * @param context context - * @param target target object - * @param methodName method name - * @param args arguments - * - * @return object - */ - Object nullMethodResult(Map context, Object target, String methodName, Object[] args); - - /** - * Property in target evaluated to null. Property can be a constant - * String property name or a DynamicSubscript. - * - * @param context context - * @param target target object - * @param property property - * - * @return object - */ - Object nullPropertyValue(Map context, Object target, Object property); -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/ObjectTypeDeterminer.java b/core/src/main/java/com/opensymphony/xwork2/conversion/ObjectTypeDeterminer.java deleted file mode 100644 index dee9b152b2..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/ObjectTypeDeterminer.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.conversion; - -/** - * Determines what the key and and element class of a Map or Collection should be. For Maps, the elements are the - * values. For Collections, the elements are the elements of the collection. - *

    - * See the implementations for javadoc description for the methods as they are dependent on the concrete implementation. - *

    - * - * @author Gabriel Zimmerman - */ -public interface ObjectTypeDeterminer { - - public Class getKeyClass(Class parentClass, String property); - - public Class getElementClass(Class parentClass, String property, Object key); - - public String getKeyProperty(Class parentClass, String property); - - public boolean shouldCreateIfNew(Class parentClass, String property, Object target, String keyProperty, boolean isIndexAccessed); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConversionException.java b/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConversionException.java deleted file mode 100644 index 82e4f3476f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConversionException.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.conversion; - -import com.opensymphony.xwork2.XWorkException; - - -/** - * TypeConversionException should be thrown by any TypeConverters which fail to convert values - * - * @author Jason Carreira - * Created Oct 3, 2003 12:18:33 AM - */ -public class TypeConversionException extends XWorkException { - - /** - * Constructs a XWorkException with no detail message. - */ - public TypeConversionException() { - } - - /** - * Constructs a XWorkException with the specified - * detail message. - * - * @param s the detail message. - */ - public TypeConversionException(String s) { - super(s); - } - - /** - * Constructs a XWorkException with no detail message. - * @param cause the cause - */ - public TypeConversionException(Throwable cause) { - super(cause); - } - - /** - * Constructs a XWorkException with the specified - * detail message. - * - * @param s the detail message. - * @param cause the cause - */ - public TypeConversionException(String s, Throwable cause) { - super(s, cause); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConverter.java deleted file mode 100644 index 0fb67d78a7..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConverter.java +++ /dev/null @@ -1,64 +0,0 @@ -//-------------------------------------------------------------------------- -// Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// Neither the name of the Drew Davidson nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -//-------------------------------------------------------------------------- -package com.opensymphony.xwork2.conversion; - -import java.lang.reflect.Member; -import java.util.Map; - -/** - * Interface for accessing the type conversion facilities within a context. - * - * This interface was copied from OGNL's TypeConverter - * - * @author Luke Blanshard (blanshlu@netscape.net) - * @author Drew Davidson (drew@ognl.org) - */ -public interface TypeConverter -{ - /** - * Converts the given value to a given type. The OGNL context, target, member and - * name of property being set are given. This method should be able to handle - * conversion in general without any context, target, member or property name specified. - * @param context context under which the conversion is being done - * @param target target object in which the property is being set - * @param member member (Constructor, Method or Field) being set - * @param propertyName property name being set - * @param value value to be converted - * @param toType type to which value is converted - * @return Converted value of type toType or TypeConverter.NoConversionPossible to indicate that the - conversion was not possible. - */ - public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType); - - public static final Object NO_CONVERSION_POSSIBLE = "ognl.NoConversionPossible"; - - public static final String TYPE_CONVERTER_CONTEXT_KEY = "_typeConverter"; -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConverterCreator.java b/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConverterCreator.java deleted file mode 100644 index 738bbe82f4..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConverterCreator.java +++ /dev/null @@ -1,17 +0,0 @@ -package com.opensymphony.xwork2.conversion; - -/** - * Instantiate converter classes, if cannot create TypeConverter throws exception - */ -public interface TypeConverterCreator { - - /** - * Creates {@link TypeConverter} from given class - * - * @param className convert class - * @return instance of {@link TypeConverter} - * @throws Exception when cannot create/cast to {@link TypeConverter} - */ - TypeConverter createTypeConverter(String className) throws Exception; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConverterHolder.java b/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConverterHolder.java deleted file mode 100644 index 6a67b8bf9f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/TypeConverterHolder.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.opensymphony.xwork2.conversion; - -import java.util.Map; - -/** - * Holds all mappings related to {@link TypeConverter}s - */ -public interface TypeConverterHolder { - - /** - * Adds mapping for default type converters - application scoped - * - * @param className name of the class with associated converter - * @param typeConverter {@link TypeConverter} instance for associated class - */ - void addDefaultMapping(String className, TypeConverter typeConverter); - - /** - * Checks if converter was already defined for given class - * - * @param className name of the class to check for - * @return true if default mapping was already specified - */ - boolean containsDefaultMapping(String className); - - /** - * Returns instance of {@link TypeConverter} associated with given class - * - * @param className name of the class to return converter for - * @return instance of {@link TypeConverter} to be used to convert class - */ - TypeConverter getDefaultMapping(String className); - - /** - * Target class conversion Mappings. - * - * @param clazz class to convert to/from - * @return {@link TypeConverter} for given class - */ - Map getMapping(Class clazz); - - /** - * Assign mapping of converters for given class - * - * @param clazz class to convert to/from - * @param mapping property converters - */ - void addMapping(Class clazz, Map mapping); - - /** - * Check if there is no mapping for given class to convert - * - * @param clazz class to convert to/from - * @return true if mapping couldn't be found - */ - boolean containsNoMapping(Class clazz); - - /** - * Adds no mapping flag for give class - * - * @param clazz class to register missing converter - */ - void addNoMapping(Class clazz); - - /** - * Checks if no mapping was defined for given class name - * FIXME lukaszlenart: maybe it should be merged with NoMapping - * - * @param className name of the class to check for - * @return true if converter was defined for given class name - */ - boolean containsUnknownMapping(String className); - - /** - * Adds no converter flag for given class name - * FIXME lukaszlenart: maybe it should be merged with NoMapping - * - * @param className name of the class to mark there is no converter for it - */ - void addUnknownMapping(String className); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/Conversion.java b/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/Conversion.java deleted file mode 100644 index aa02df766a..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/Conversion.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.conversion.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * A marker annotation for type conversions at Type level. - * - * - *

    - * Annotation usage: - *

    - * - * - * The Conversion annotation must be applied at Type level. - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    ParameterRequiredDefaultDescription
    conversionno used for Type Conversions applied at Type level.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @Conversion(
    - *     conversions = {
    - *          // key must be the name of a property for which converter should be used
    - *          @TypeConversion(key = "date", converter = "org.demo.converter.DateConverter")
    - *     }
    - * )
    - * public class ConversionAction implements Action {
    - *
    - *     private Date date;
    - *
    - *     public setDate(Date date) {
    - *         this.date = date;
    - *     }
    - *
    - *     public Date getDate() {
    - *         return date;
    - *     }
    - *
    - * }
    - *
    - * 
    - * 
    - * - * @author Rainer Hermanns - * @version $Id$ - */ -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface Conversion { - - /** - * Allow Type Conversions being applied at Type level. - * - * @return type conversion - */ - TypeConversion[] conversions() default {}; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/ConversionRule.java b/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/ConversionRule.java deleted file mode 100644 index e30bea48aa..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/ConversionRule.java +++ /dev/null @@ -1,33 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.conversion.annotations; - -/** - * ConversionRule - * - * @author Rainer Hermanns - * @version $Id$ - */ -public enum ConversionRule { - - PROPERTY, COLLECTION, MAP, KEY, KEY_PROPERTY, ELEMENT, CREATE_IF_NULL; - - @Override - public String toString() { - return super.toString().toUpperCase(); - } -} - diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/ConversionType.java b/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/ConversionType.java deleted file mode 100644 index d80a926860..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/ConversionType.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.conversion.annotations; - -/** - * ConversionType - * - * @author Rainer Hermanns - * @version $Id$ - */ -public enum ConversionType { - - - APPLICATION, CLASS; - - @Override - public String toString() { - return super.toString().toUpperCase(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/TypeConversion.java b/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/TypeConversion.java deleted file mode 100644 index 6640659a05..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/TypeConversion.java +++ /dev/null @@ -1,190 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.conversion.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - *

    This annotation is used for class and application wide conversion rules.

    - * - *

    - * Class wide conversion:
    - * The conversion rules will be assembled in a file called XXXAction-conversion.properties - * within the same package as the related action class. - * Set type to: type = ConversionType.CLASS - *

    - * - *

    - * Application wide conversion:
    - * The conversion rules will be assembled within the xwork-conversion.properties file within the classpath root. - * Set type to: type = ConversionType.APPLICATION - *

    - * - * - *

    Annotation usage:

    - * - * - *

    The TypeConversion annotation can be applied at property and method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    ParameterRequiredDefaultDescription
    keynoThe annotated property/key nameThe optional property name mostly used within TYPE level annotations.
    typenoConversionType.CLASSEnum value of ConversionType. Determines whether the conversion should be applied at application or class level.
    rulenoConversionRule.PROPERTYEnum value of ConversionRule. The ConversionRule can be a property, a Collection or a Map.
    convertereither this or value The class name of the TypeConverter to be used as converter.
    valueeither converter or this The value to set for ConversionRule.KEY_PROPERTY.
    - * - * - * - *

    Example code:

    - * - *
    - * 
    - * @Conversion()
    - * public class ConversionAction implements Action {
    - *
    - *   private String convertInt;
    - *
    - *   private String convertDouble;
    - *   private List users = null;
    - *
    - *   private HashMap keyValues = null;
    - *
    - *   @TypeConversion(type = ConversionType.APPLICATION, converter = "com.opensymphony.xwork2.util.XWorkBasicConverter")
    - *   public void setConvertInt( String convertInt ) {
    - *       this.convertInt = convertInt;
    - *   }
    - *
    - *   @TypeConversion(converter = "com.opensymphony.xwork2.util.XWorkBasicConverter")
    - *   public void setConvertDouble( String convertDouble ) {
    - *       this.convertDouble = convertDouble;
    - *   }
    - *
    - *   @TypeConversion(rule = ConversionRule.COLLECTION, converter = "java.util.String")
    - *   public void setUsers( List users ) {
    - *       this.users = users;
    - *   }
    - *
    - *   @TypeConversion(rule = ConversionRule.MAP, converter = "java.math.BigInteger")
    - *   public void setKeyValues( HashMap keyValues ) {
    - *       this.keyValues = keyValues;
    - *   }
    - *
    - *   @TypeConversion(type = ConversionType.APPLICATION, property = "java.util.Date", converter = "com.opensymphony.xwork2.util.XWorkBasicConverter")
    - *   public String execute() throws Exception {
    - *       return SUCCESS;
    - *   }
    - * }
    - * 
    - * 
    - * - * @author Rainer Hermanns - * @version $Id$ - */ -@Target({ ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface TypeConversion { - - /** - * The optional key name used within TYPE level annotations. - * Defaults to the property name. - * - * @return key - */ - String key() default ""; - - /** - * The ConversionType can be either APPLICATION or CLASS. - * Defaults to CLASS. - * - * Note: If you use ConversionType.APPLICATION, you can not set a value! - * - * @return the conversion type - */ - ConversionType type() default ConversionType.CLASS; - - /** - * The ConversionRule can be a PROPERTY, KEY, KEY_PROPERTY, ELEMENT, COLLECTION (deprecated) or a MAP. - * Note: Collection and Map conversion rules can be determined via com.opensymphony.xwork2.util.DefaultObjectTypeDeterminer. - * - * @see com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer - * - * @return the conversion rule - */ - ConversionRule rule() default ConversionRule.PROPERTY; - - /** - * The class of the TypeConverter to be used as converter. - * - * Note: This can not be used with ConversionRule.KEY_PROPERTY! - * - * @return class of the TypeConverter to be used as converter - */ - String converter() default ""; - - /** - * If used with ConversionRule.KEY_PROPERTY specify a value here! - * - * Note: If you use ConversionType.APPLICATION, you can not set a value! - * - * @return value - */ - String value() default ""; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/package.html b/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/package.html deleted file mode 100644 index e2a91d0a1a..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/annotations/package.html +++ /dev/null @@ -1 +0,0 @@ -Type conversion annotations. diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/ArrayConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/ArrayConverter.java deleted file mode 100644 index 09addae854..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/ArrayConverter.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.conversion.TypeConverter; - -import java.lang.reflect.Array; -import java.lang.reflect.Member; -import java.util.Map; - -public class ArrayConverter extends DefaultTypeConverter { - - @Override - public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType) { - Object result = null; - Class componentType = toType.getComponentType(); - - if (componentType != null) { - TypeConverter converter = getTypeConverter(context); - - if (value.getClass().isArray()) { - int length = Array.getLength(value); - result = Array.newInstance(componentType, length); - - for (int i = 0; i < length; i++) { - Object valueItem = Array.get(value, i); - Array.set(result, i, converter.convertValue(context, target, member, propertyName, valueItem, componentType)); - } - } else { - result = Array.newInstance(componentType, 1); - Array.set(result, 0, converter.convertValue(context, target, member, propertyName, value, componentType)); - } - } - - return result; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/CollectionConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/CollectionConverter.java deleted file mode 100644 index df7cf8cf3b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/CollectionConverter.java +++ /dev/null @@ -1,96 +0,0 @@ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer; -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.XWorkList; - -import java.lang.reflect.Member; -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; -import java.util.SortedSet; -import java.util.TreeSet; - -public class CollectionConverter extends DefaultTypeConverter { - - private ObjectTypeDeterminer objectTypeDeterminer; - - @Inject - public void setObjectTypeDeterminer(ObjectTypeDeterminer determiner) { - this.objectTypeDeterminer = determiner; - } - - public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType) { - Collection result; - Class memberType = String.class; - - if (target != null) { - memberType = objectTypeDeterminer.getElementClass(target.getClass(), propertyName, null); - - if (memberType == null) { - memberType = String.class; - } - } - - if (toType.isAssignableFrom(value.getClass())) { - // no need to do anything - result = (Collection) value; - } else if (value.getClass().isArray()) { - Object[] objArray = (Object[]) value; - TypeConverter converter = getTypeConverter(context); - result = createCollection(toType, memberType, objArray.length); - - for (Object anObjArray : objArray) { - Object convertedValue = converter.convertValue(context, target, member, propertyName, anObjArray, memberType); - if (!TypeConverter.NO_CONVERSION_POSSIBLE.equals(convertedValue)) { - result.add(convertedValue); - } - } - } else if (Collection.class.isAssignableFrom(value.getClass())) { - Collection col = (Collection) value; - TypeConverter converter = getTypeConverter(context); - result = createCollection(toType, memberType, col.size()); - - for (Object aCol : col) { - Object convertedValue = converter.convertValue(context, target, member, propertyName, aCol, memberType); - if (!TypeConverter.NO_CONVERSION_POSSIBLE.equals(convertedValue)) { - result.add(convertedValue); - } - } - } else { - result = createCollection(toType, memberType, -1); - TypeConverter converter = getTypeConverter(context); - Object convertedValue = converter.convertValue(context, target, member, propertyName, value, memberType); - if (!TypeConverter.NO_CONVERSION_POSSIBLE.equals(convertedValue)) { - result.add(convertedValue); - } - } - - return result; - } - - private Collection createCollection(Class toType, Class memberType, int size) { - Collection result; - - if (toType == Set.class) { - if (size > 0) { - result = new HashSet(size); - } else { - result = new HashSet(); - } - } else if (toType == SortedSet.class) { - result = new TreeSet(); - } else { - if (size > 0) { - result = new XWorkList(memberType, size); - } else { - result = new XWorkList(memberType); - } - } - - return result; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DateConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DateConverter.java deleted file mode 100644 index bde36f7733..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DateConverter.java +++ /dev/null @@ -1,102 +0,0 @@ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.XWorkException; - -import java.lang.reflect.Constructor; -import java.lang.reflect.Member; -import java.text.DateFormat; -import java.text.ParseException; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Locale; -import java.util.Map; - -public class DateConverter extends DefaultTypeConverter { - - @Override - public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType) { - Date result = null; - - if (value instanceof String && value != null && ((String) value).length() > 0) { - String sa = (String) value; - Locale locale = getLocale(context); - - DateFormat df = null; - if (java.sql.Time.class == toType) { - df = DateFormat.getTimeInstance(DateFormat.MEDIUM, locale); - } else if (java.sql.Timestamp.class == toType) { - Date check = null; - SimpleDateFormat dtfmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT, - DateFormat.MEDIUM, - locale); - SimpleDateFormat fullfmt = new SimpleDateFormat(dtfmt.toPattern() + MILLISECOND_FORMAT, - locale); - - SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, - locale); - - SimpleDateFormat[] fmts = {fullfmt, dtfmt, dfmt}; - for (SimpleDateFormat fmt : fmts) { - try { - check = fmt.parse(sa); - df = fmt; - if (check != null) { - break; - } - } catch (ParseException ignore) { - } - } - } else if (java.util.Date.class == toType) { - Date check; - DateFormat[] dfs = getDateFormats(locale); - for (DateFormat df1 : dfs) { - try { - check = df1.parse(sa); - df = df1; - if (check != null) { - break; - } - } catch (ParseException ignore) { - } - } - } - //final fallback for dates without time - if (df == null) { - df = DateFormat.getDateInstance(DateFormat.SHORT, locale); - } - try { - df.setLenient(false); // let's use strict parsing (XW-341) - result = df.parse(sa); - if (!(Date.class == toType)) { - try { - Constructor constructor = toType.getConstructor(new Class[]{long.class}); - return constructor.newInstance(new Object[]{Long.valueOf(result.getTime())}); - } catch (Exception e) { - throw new XWorkException("Couldn't create class " + toType + " using default (long) constructor", e); - } - } - } catch (ParseException e) { - throw new XWorkException("Could not parse date", e); - } - } else if (Date.class.isAssignableFrom(value.getClass())) { - result = (Date) value; - } - return result; - } - - private DateFormat[] getDateFormats(Locale locale) { - DateFormat dt1 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, locale); - DateFormat dt2 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale); - DateFormat dt3 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.SHORT, locale); - - DateFormat d1 = DateFormat.getDateInstance(DateFormat.SHORT, locale); - DateFormat d2 = DateFormat.getDateInstance(DateFormat.MEDIUM, locale); - DateFormat d3 = DateFormat.getDateInstance(DateFormat.LONG, locale); - - DateFormat rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss"); - DateFormat rfc3339dateOnly = new SimpleDateFormat("yyyy-MM-dd"); - - return new DateFormat[]{dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly}; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionAnnotationProcessor.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionAnnotationProcessor.java deleted file mode 100644 index c3faae3a52..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionAnnotationProcessor.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.conversion.ConversionAnnotationProcessor; -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.conversion.TypeConverterCreator; -import com.opensymphony.xwork2.conversion.TypeConverterHolder; -import com.opensymphony.xwork2.conversion.annotations.ConversionRule; -import com.opensymphony.xwork2.conversion.annotations.ConversionType; -import com.opensymphony.xwork2.conversion.annotations.TypeConversion; -import com.opensymphony.xwork2.inject.Inject; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.Map; - -/** - * Default implementation of {@link ConversionAnnotationProcessor} - */ -public class DefaultConversionAnnotationProcessor implements ConversionAnnotationProcessor { - - private static final Logger LOG = LogManager.getLogger(DefaultConversionAnnotationProcessor.class); - - private TypeConverterCreator converterCreator; - private TypeConverterHolder converterHolder; - - @Inject - public void setTypeConverterCreator(TypeConverterCreator converterCreator) { - this.converterCreator = converterCreator; - } - - @Inject - public void setTypeConverterHolder(TypeConverterHolder converterHolder) { - this.converterHolder = converterHolder; - } - - public void process(Map mapping, TypeConversion tc, String key) { - LOG.debug("TypeConversion [{}] with key: [{}]", tc.converter(), key); - if (key == null) { - return; - } - try { - if (tc.type() == ConversionType.APPLICATION) { - converterHolder.addDefaultMapping(key, converterCreator.createTypeConverter(tc.converter())); - } else { - if (tc.rule() == ConversionRule.KEY_PROPERTY || tc.rule() == ConversionRule.CREATE_IF_NULL) { - mapping.put(key, tc.value()); - } - //for properties of classes - else if (tc.rule() != ConversionRule.ELEMENT || tc.rule() == ConversionRule.KEY || tc.rule() == ConversionRule.COLLECTION) { - mapping.put(key, converterCreator.createTypeConverter(tc.converter())); - } - //for keys of Maps - else if (tc.rule() == ConversionRule.KEY) { - Class converterClass = Thread.currentThread().getContextClassLoader().loadClass(tc.converter()); - LOG.debug("Converter class: [{}]", converterClass); - //check if the converter is a type converter if it is one - //then just put it in the map as is. Otherwise - //put a value in for the type converter of the class - if (converterClass.isAssignableFrom(TypeConverter.class)) { - mapping.put(key, converterCreator.createTypeConverter(tc.converter())); - } else { - mapping.put(key, converterClass); - LOG.debug("Object placed in mapping for key [{}] is [{}]", key, mapping.get(key)); - } - } - //elements(values) of maps / lists - else { - mapping.put(key, Thread.currentThread().getContextClassLoader().loadClass(tc.converter())); - } - } - } catch (Exception e) { - LOG.debug("Got exception for {}", key, e); - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionFileProcessor.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionFileProcessor.java deleted file mode 100644 index 488d9ce855..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionFileProcessor.java +++ /dev/null @@ -1,98 +0,0 @@ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.FileManager; -import com.opensymphony.xwork2.FileManagerFactory; -import com.opensymphony.xwork2.conversion.ConversionFileProcessor; -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.conversion.TypeConverterCreator; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ClassLoaderUtil; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.InputStream; -import java.util.Map; -import java.util.Properties; - -/** - * Default implementation of {@link ConversionFileProcessor} - */ -public class DefaultConversionFileProcessor implements ConversionFileProcessor { - - private static final Logger LOG = LogManager.getLogger(DefaultConversionFileProcessor.class); - - private FileManager fileManager; - private TypeConverterCreator converterCreator; - - @Inject - public void setFileManagerFactory(FileManagerFactory factory) { - fileManager = factory.getFileManager(); - } - - @Inject - public void setTypeConverterCreator(TypeConverterCreator converterCreator) { - this.converterCreator = converterCreator; - } - - public void process(Map mapping, Class clazz, String converterFilename) { - try { - InputStream is = fileManager.loadFile(ClassLoaderUtil.getResource(converterFilename, clazz)); - - if (is != null) { - LOG.debug("Processing conversion file [{}] for class [{}]", converterFilename, clazz); - - Properties prop = new Properties(); - prop.load(is); - - for (Map.Entry entry : prop.entrySet()) { - String key = (String) entry.getKey(); - - if (mapping.containsKey(key)) { - break; - } - // for keyProperty of Set - if (key.startsWith(DefaultObjectTypeDeterminer.KEY_PROPERTY_PREFIX) - || key.startsWith(DefaultObjectTypeDeterminer.CREATE_IF_NULL_PREFIX)) { - LOG.debug("\t{}:{} [treated as String]", key, entry.getValue()); - mapping.put(key, entry.getValue()); - } - //for properties of classes - else if (!(key.startsWith(DefaultObjectTypeDeterminer.ELEMENT_PREFIX) || - key.startsWith(DefaultObjectTypeDeterminer.KEY_PREFIX) || - key.startsWith(DefaultObjectTypeDeterminer.DEPRECATED_ELEMENT_PREFIX)) - ) { - TypeConverter _typeConverter = converterCreator.createTypeConverter((String) entry.getValue()); - LOG.debug("\t{}:{} [treated as TypeConverter {}]", key, entry.getValue(), _typeConverter); - mapping.put(key, _typeConverter); - } - //for keys of Maps - else if (key.startsWith(DefaultObjectTypeDeterminer.KEY_PREFIX)) { - - Class converterClass = Thread.currentThread().getContextClassLoader().loadClass((String) entry.getValue()); - - //check if the converter is a type converter if it is one - //then just put it in the map as is. Otherwise - //put a value in for the type converter of the class - if (converterClass.isAssignableFrom(TypeConverter.class)) { - TypeConverter _typeConverter = converterCreator.createTypeConverter((String) entry.getValue()); - LOG.debug("\t{}:{} [treated as TypeConverter {}]", key, entry.getValue(), _typeConverter); - mapping.put(key, _typeConverter); - } else { - LOG.debug("\t{}:{} [treated as Class {}]", key, entry.getValue(), converterClass); - mapping.put(key, converterClass); - } - } - //elements(values) of maps / lists - else { - Class _c = Thread.currentThread().getContextClassLoader().loadClass((String) entry.getValue()); - LOG.debug("\t{}:{} [treated as Class {}]", key, entry.getValue(), _c); - mapping.put(key, _c); - } - } - } - } catch (Exception ex) { - LOG.error("Problem loading properties for {}", clazz.getName(), ex); - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionPropertiesProcessor.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionPropertiesProcessor.java deleted file mode 100644 index 762496f7b0..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultConversionPropertiesProcessor.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.XWorkException; -import com.opensymphony.xwork2.conversion.ConversionPropertiesProcessor; -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.conversion.TypeConverterCreator; -import com.opensymphony.xwork2.conversion.TypeConverterHolder; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ClassLoaderUtil; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -import java.io.IOException; -import java.net.URL; -import java.util.Iterator; -import java.util.Map; -import java.util.Properties; - -/** - * TODO lukaszlenart: add a comment - */ -public class DefaultConversionPropertiesProcessor implements ConversionPropertiesProcessor { - - private static final Logger LOG = LogManager.getLogger(DefaultConversionPropertiesProcessor.class); - - private TypeConverterCreator converterCreator; - private TypeConverterHolder converterHolder; - - @Inject - public void setTypeConverterCreator(TypeConverterCreator converterCreator) { - this.converterCreator = converterCreator; - } - - @Inject - public void setTypeConverterHolder(TypeConverterHolder converterHolder) { - this.converterHolder = converterHolder; - } - - public void process(String propsName) { - loadConversionProperties(propsName, false); - } - - public void processRequired(String propsName) { - loadConversionProperties(propsName, true); - } - - public void loadConversionProperties(String propsName, boolean require) { - try { - Iterator resources = ClassLoaderUtil.getResources(propsName, getClass(), true); - while (resources.hasNext()) { - URL url = resources.next(); - Properties props = new Properties(); - props.load(url.openStream()); - - LOG.debug("Processing conversion file [{}]", propsName); - - for (Object o : props.entrySet()) { - Map.Entry entry = (Map.Entry) o; - String key = (String) entry.getKey(); - - try { - TypeConverter _typeConverter = converterCreator.createTypeConverter((String) entry.getValue()); - if (LOG.isDebugEnabled()) { - LOG.debug("\t{}:{} [treated as TypeConverter {}]", key, entry.getValue(), _typeConverter); - } - converterHolder.addDefaultMapping(key, _typeConverter); - } catch (Exception e) { - LOG.error("Conversion registration error", e); - } - } - } - } catch (IOException ex) { - if (require) { - throw new XWorkException("Cannot load conversion properties file: "+propsName, ex); - } else { - LOG.debug("Cannot load conversion properties file: {}", propsName, ex); - } - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java deleted file mode 100644 index f191680c58..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverter.java +++ /dev/null @@ -1,359 +0,0 @@ -//-------------------------------------------------------------------------- -// Copyright (c) 1998-2004, Drew Davidson and Luke Blanshard -// All rights reserved. -// -// Redistribution and use in source and binary forms, with or without -// modification, are permitted provided that the following conditions are -// met: -// -// Redistributions of source code must retain the above copyright notice, -// this list of conditions and the following disclaimer. -// Redistributions in binary form must reproduce the above copyright -// notice, this list of conditions and the following disclaimer in the -// documentation and/or other materials provided with the distribution. -// Neither the name of the Drew Davidson nor the names of its contributors -// may be used to endorse or promote products derived from this software -// without specific prior written permission. -// -// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS -// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT -// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS -// FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE -// COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, -// INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, -// BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS -// OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED -// AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, -// OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF -// THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH -// DAMAGE. -//-------------------------------------------------------------------------- -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.LocaleProvider; -import com.opensymphony.xwork2.LocaleProviderFactory; -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.ognl.XWorkTypeConverterWrapper; - -import java.lang.reflect.Array; -import java.lang.reflect.Member; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.util.Collections; -import java.util.HashMap; -import java.util.Locale; -import java.util.Map; - -/** - * Default type conversion. Converts among numeric types and also strings. Contains the basic - * type mapping code from OGNL. - * - * @author Luke Blanshard (blanshlu@netscape.net) - * @author Drew Davidson (drew@ognl.org) - */ -public abstract class DefaultTypeConverter implements TypeConverter { - - protected static String MILLISECOND_FORMAT = ".SSS"; - - private static final String NULL_STRING = "null"; - - private static final Map primitiveDefaults; - - private Container container; - - static { - Map map = new HashMap<>(); - map.put(Boolean.TYPE, Boolean.FALSE); - map.put(Byte.TYPE, Byte.valueOf((byte) 0)); - map.put(Short.TYPE, Short.valueOf((short) 0)); - map.put(Character.TYPE, new Character((char) 0)); - map.put(Integer.TYPE, Integer.valueOf(0)); - map.put(Long.TYPE, Long.valueOf(0L)); - map.put(Float.TYPE, new Float(0.0f)); - map.put(Double.TYPE, new Double(0.0)); - map.put(BigInteger.class, new BigInteger("0")); - map.put(BigDecimal.class, new BigDecimal(0.0)); - primitiveDefaults = Collections.unmodifiableMap(map); - } - - @Inject - public void setContainer(Container container) { - this.container = container; - } - - public Object convertValue(Map context, Object value, Class toType) { - return convertValue(value, toType); - } - - public Object convertValue(Map context, Object target, Member member, - String propertyName, Object value, Class toType) { - return convertValue(context, value, toType); - } - - public TypeConverter getTypeConverter( Map context ) - { - Object obj = context.get(TypeConverter.TYPE_CONVERTER_CONTEXT_KEY); - if (obj instanceof TypeConverter) { - return (TypeConverter) obj; - - // for backwards-compatibility - } else if (obj instanceof ognl.TypeConverter) { - return new XWorkTypeConverterWrapper((ognl.TypeConverter) obj); - } - return null; - } - - /** - * Returns the value converted numerically to the given class type - * - * This method also detects when arrays are being converted and converts the - * components of one array to the type of the other. - * - * @param value - * an object to be converted to the given type - * @param toType - * class type to be converted to - * @return converted value of the type given, or value if the value cannot - * be converted to the given type. - */ - public Object convertValue(Object value, Class toType) { - Object result = null; - - if (value != null) { - /* If array -> array then convert components of array individually */ - if (value.getClass().isArray() && toType.isArray()) { - Class componentType = toType.getComponentType(); - - result = Array.newInstance(componentType, Array - .getLength(value)); - for (int i = 0, icount = Array.getLength(value); i < icount; i++) { - Array.set(result, i, convertValue(Array.get(value, i), - componentType)); - } - } else { - if ((toType == Integer.class) || (toType == Integer.TYPE)) - result = (int) longValue(value); - if ((toType == Double.class) || (toType == Double.TYPE)) - result = doubleValue(value); - if ((toType == Boolean.class) || (toType == Boolean.TYPE)) - result = booleanValue(value) ? Boolean.TRUE : Boolean.FALSE; - if ((toType == Byte.class) || (toType == Byte.TYPE)) - result = (byte) longValue(value); - if ((toType == Character.class) || (toType == Character.TYPE)) - result = (char) longValue(value); - if ((toType == Short.class) || (toType == Short.TYPE)) - result = (short) longValue(value); - if ((toType == Long.class) || (toType == Long.TYPE)) - result = longValue(value); - if ((toType == Float.class) || (toType == Float.TYPE)) - result = new Float(doubleValue(value)); - if (toType == BigInteger.class) - result = bigIntValue(value); - if (toType == BigDecimal.class) - result = bigDecValue(value); - if (toType == String.class) - result = stringValue(value); - if (Enum.class.isAssignableFrom(toType)) - result = enumValue(toType, value); - } - } else { - if (toType.isPrimitive()) { - result = primitiveDefaults.get(toType); - } - } - return result; - } - - /** - * Evaluates the given object as a boolean: if it is a Boolean object, it's - * easy; if it's a Number or a Character, returns true for non-zero objects; - * and otherwise returns true for non-null objects. - * - * @param value - * an object to interpret as a boolean - * @return the boolean value implied by the given object - */ - public static boolean booleanValue(Object value) { - if (value == null) - return false; - Class c = value.getClass(); - if (c == Boolean.class) - return (Boolean) value; - // if ( c == String.class ) - // return ((String)value).length() > 0; - if (c == Character.class) - return (Character) value != 0; - if (value instanceof Number) - return ((Number) value).doubleValue() != 0; - return true; // non-null - } - - public Enum enumValue(Class toClass, Object o) { - Enum result = null; - if (o == null) { - result = null; - } else if (o instanceof String[]) { - result = Enum.valueOf(toClass, ((String[]) o)[0]); - } else if (o instanceof String) { - result = Enum.valueOf(toClass, (String) o); - } - return result; - } - - /** - * Evaluates the given object as a long integer. - * - * @param value - * an object to interpret as a long integer - * @return the long integer value implied by the given object - * @throws NumberFormatException - * if the given object can't be understood as a long integer - */ - public static long longValue(Object value) throws NumberFormatException { - if (value == null) - return 0L; - Class c = value.getClass(); - if (c.getSuperclass() == Number.class) - return ((Number) value).longValue(); - if (c == Boolean.class) - return (Boolean) value ? 1 : 0; - if (c == Character.class) - return (Character) value; - return Long.parseLong(stringValue(value, true)); - } - - /** - * Evaluates the given object as a double-precision floating-point number. - * - * @param value - * an object to interpret as a double - * @return the double value implied by the given object - * @throws NumberFormatException - * if the given object can't be understood as a double - */ - public static double doubleValue(Object value) throws NumberFormatException { - if (value == null) - return 0.0; - Class c = value.getClass(); - if (c.getSuperclass() == Number.class) - return ((Number) value).doubleValue(); - if (c == Boolean.class) - return (Boolean) value ? 1 : 0; - if (c == Character.class) - return (Character) value; - String s = stringValue(value, true); - - return (s.length() == 0) ? 0.0 : Double.parseDouble(s); - /* - * For 1.1 parseDouble() is not available - */ - // return Double.valueOf( value.toString() ).doubleValue(); - } - - /** - * Evaluates the given object as a BigInteger. - * - * @param value - * an object to interpret as a BigInteger - * @return the BigInteger value implied by the given object - * @throws NumberFormatException - * if the given object can't be understood as a BigInteger - */ - public static BigInteger bigIntValue(Object value) - throws NumberFormatException { - if (value == null) - return BigInteger.valueOf(0L); - Class c = value.getClass(); - if (c == BigInteger.class) - return (BigInteger) value; - if (c == BigDecimal.class) - return ((BigDecimal) value).toBigInteger(); - if (c.getSuperclass() == Number.class) - return BigInteger.valueOf(((Number) value).longValue()); - if (c == Boolean.class) - return BigInteger.valueOf((Boolean) value ? 1 : 0); - if (c == Character.class) - return BigInteger.valueOf(((Character) value).charValue()); - return new BigInteger(stringValue(value, true)); - } - - /** - * Evaluates the given object as a BigDecimal. - * - * @param value - * an object to interpret as a BigDecimal - * @return the BigDecimal value implied by the given object - * @throws NumberFormatException - * if the given object can't be understood as a BigDecimal - */ - public static BigDecimal bigDecValue(Object value) - throws NumberFormatException { - if (value == null) - return BigDecimal.valueOf(0L); - Class c = value.getClass(); - if (c == BigDecimal.class) - return (BigDecimal) value; - if (c == BigInteger.class) - return new BigDecimal((BigInteger) value); - if (c.getSuperclass() == Number.class) - return new BigDecimal(((Number) value).doubleValue()); - if (c == Boolean.class) - return BigDecimal.valueOf((Boolean) value ? 1 : 0); - if (c == Character.class) - return BigDecimal.valueOf(((Character) value).charValue()); - return new BigDecimal(stringValue(value, true)); - } - - /** - * Evaluates the given object as a String and trims it if the trim flag is - * true. - * - * @param value - * an object to interpret as a String - * @param trim - * trims the result if true - * @return the String value implied by the given object as returned by the - * toString() method, or "null" if the object is null. - */ - public static String stringValue(Object value, boolean trim) { - String result; - - if (value == null) { - result = NULL_STRING; - } else { - result = value.toString(); - if (trim) { - result = result.trim(); - } - } - return result; - } - - /** - * Evaluates the given object as a String. - * - * @param value - * an object to interpret as a String - * @return the String value implied by the given object as returned by the - * toString() method, or "null" if the object is null. - */ - public static String stringValue(Object value) { - return stringValue(value, false); - } - - protected Locale getLocale(Map context) { - Locale locale = null; - if (context != null) { - locale = (Locale) context.get(ActionContext.LOCALE); - } - if (locale == null) { - LocaleProviderFactory localeProviderFactory = container.getInstance(LocaleProviderFactory.class); - locale = localeProviderFactory.createLocaleProvider().getLocale(); - } - return locale; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverterCreator.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverterCreator.java deleted file mode 100644 index ed6ac22657..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverterCreator.java +++ /dev/null @@ -1,35 +0,0 @@ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.conversion.TypeConverterCreator; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.ognl.XWorkTypeConverterWrapper; - -/** - * Default implementation of {@link TypeConverterCreator} - */ -public class DefaultTypeConverterCreator implements TypeConverterCreator { - - private ObjectFactory objectFactory; - - @Inject - public void setObjectFactory(ObjectFactory objectFactory) { - this.objectFactory = objectFactory; - } - - public TypeConverter createTypeConverter(String className) throws Exception { - // type converters are used across users - Object obj = objectFactory.buildBean(className, null); - if (obj instanceof TypeConverter) { - return (TypeConverter) obj; - - // For backwards compatibility - } else if (obj instanceof ognl.TypeConverter) { - return new XWorkTypeConverterWrapper((ognl.TypeConverter) obj); - } else { - throw new IllegalArgumentException("Type converter class " + obj.getClass() + " doesn't implement com.opensymphony.xwork2.conversion.TypeConverter"); - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverterHolder.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverterHolder.java deleted file mode 100644 index c05ed8f303..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/DefaultTypeConverterHolder.java +++ /dev/null @@ -1,97 +0,0 @@ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.conversion.TypeConverterHolder; - -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; - -/** - * Default implementation of {@link TypeConverterHolder} - */ -public class DefaultTypeConverterHolder implements TypeConverterHolder { - - /** - * Record class and its type converter mapping. - *
    -     * - String - classname as String
    -     * - TypeConverter - instance of TypeConverter
    -     * 
    - */ - private HashMap defaultMappings = new HashMap<>(); // non-action (eg. returned value) - - /** - * Target class conversion Mappings. - *
    -     * Map>
    -     *  - Class -> convert to class
    -     *  - Map
    -     *    - String -> property name
    -     *                eg. Element_property, property etc.
    -     *    - Object -> String to represent properties
    -     *                eg. value part of
    -     *                    KeyProperty_property=id
    -     *             -> TypeConverter to represent an Ognl TypeConverter
    -     *                eg. value part of
    -     *                    property=foo.bar.MyConverter
    -     *             -> Class to represent a class
    -     *                eg. value part of
    -     *                    Element_property=foo.bar.MyObject
    -     * 
    - */ - private HashMap> mappings = new HashMap<>(); // action - - /** - * Unavailable target class conversion mappings, serves as a simple cache. - */ - private HashSet noMapping = new HashSet<>(); // action - - /** - * Record classes that doesn't have conversion mapping defined. - *
    -     * - String -> classname as String
    -     * 
    - */ - protected HashSet unknownMappings = new HashSet<>(); // non-action (eg. returned value) - - public void addDefaultMapping(String className, TypeConverter typeConverter) { - defaultMappings.put(className, typeConverter); - if (unknownMappings.contains(className)) { - unknownMappings.remove(className); - } - } - - public boolean containsDefaultMapping(String className) { - return defaultMappings.containsKey(className); - } - - public TypeConverter getDefaultMapping(String className) { - return defaultMappings.get(className); - } - - public Map getMapping(Class clazz) { - return mappings.get(clazz); - } - - public void addMapping(Class clazz, Map mapping) { - mappings.put(clazz, mapping); - } - - public boolean containsNoMapping(Class clazz) { - return noMapping.contains(clazz); - } - - public void addNoMapping(Class clazz) { - noMapping.add(clazz); - } - - public boolean containsUnknownMapping(String className) { - return unknownMappings.contains(className); - } - - public void addUnknownMapping(String className) { - unknownMappings.add(className); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/InstantiatingNullHandler.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/InstantiatingNullHandler.java deleted file mode 100644 index e94eb4e12d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/InstantiatingNullHandler.java +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.conversion.NullHandler; -import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.reflection.ReflectionContextState; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.beans.PropertyDescriptor; -import java.util.*; - - -/** - * - *

    - * Provided that the key {@link ReflectionContextState#CREATE_NULL_OBJECTS} is in the action context with a value of true (this key is set - * only during the execution of the {@link com.opensymphony.xwork2.interceptor.ParametersInterceptor}), OGNL expressions - * that have caused a NullPointerException will be temporarily stopped for evaluation while the system automatically - * tries to solve the null references by automatically creating the object. - *

    - * - *

    The following rules are used when handling null references:

    - * - *
      - *
    • If the property is declared exactly as a {@link Collection} or {@link List}, then an ArrayList shall be - * returned and assigned to the null references.
    • - *
    • If the property is declared as a {@link Map}, then a HashMap will be returned and assigned to the null - * references.
    • - *
    • If the null property is a simple bean with a no-arg constructor, it will simply be created using the {@link - * ObjectFactory#buildBean(java.lang.Class, java.util.Map)} method.
    • - *
    - * - * - * - * - *

    - * For example, if a form element has a text field named person.name and the expression person evaluates - * to null, then this class will be invoked. Because the person expression evaluates to a Person class, a - * new Person is created and assigned to the null reference. Finally, the name is set on that object and the overall - * effect is that the system automatically created a Person object for you, set it by calling setUsers() and then - * finally called getUsers().setName() as you would typically expect. - *

    - * - * - * @author Matt Ho - * @author Patrick Lightbody - */ -public class InstantiatingNullHandler implements NullHandler { - - private static final Logger LOG = LogManager.getLogger(InstantiatingNullHandler.class); - - private ReflectionProvider reflectionProvider; - private ObjectFactory objectFactory; - private ObjectTypeDeterminer objectTypeDeterminer; - - @Inject - public void setObjectTypeDeterminer(ObjectTypeDeterminer det) { - this.objectTypeDeterminer = det; - } - - @Inject - public void setReflectionProvider(ReflectionProvider prov) { - this.reflectionProvider = prov; - } - - @Inject - public void setObjectFactory(ObjectFactory fac) { - this.objectFactory = fac; - } - - public Object nullMethodResult(Map context, Object target, String methodName, Object[] args) { - LOG.debug("Entering nullMethodResult"); - return null; - } - - public Object nullPropertyValue(Map context, Object target, Object property) { - LOG.debug("Entering nullPropertyValue [target={}, property={}]", target, property); - boolean c = ReflectionContextState.isCreatingNullObjects(context); - - if (!c) { - return null; - } - - if ((target == null) || (property == null)) { - return null; - } - - try { - String propName = property.toString(); - Object realTarget = reflectionProvider.getRealTarget(propName, context, target); - Class clazz = null; - - if (realTarget != null) { - PropertyDescriptor pd = reflectionProvider.getPropertyDescriptor(realTarget.getClass(), propName); - if (pd == null) { - return null; - } - - clazz = pd.getPropertyType(); - } - - if (clazz == null) { - // can't do much here! - return null; - } - - Object param = createObject(clazz, realTarget, propName, context); - - reflectionProvider.setValue(propName, context, realTarget, param); - - return param; - } catch (Exception e) { - LOG.error("Could not create and/or set value back on to object", e); - } - - return null; - } - - private Object createObject(Class clazz, Object target, String property, Map context) throws Exception { - if (Set.class.isAssignableFrom(clazz)) { - return new HashSet(); - } else if (Collection.class.isAssignableFrom(clazz)) { - return new ArrayList(); - } else if (clazz == Map.class) { - return new HashMap(); - } else if (clazz == EnumMap.class) { - Class keyClass = objectTypeDeterminer.getKeyClass(target.getClass(), property); - return new EnumMap(keyClass); - } - - return objectFactory.buildBean(clazz, context); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/NumberConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/NumberConverter.java deleted file mode 100644 index ab6efc0c35..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/NumberConverter.java +++ /dev/null @@ -1,118 +0,0 @@ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.XWorkException; - -import java.lang.reflect.Member; -import java.math.BigDecimal; -import java.math.BigInteger; -import java.text.NumberFormat; -import java.text.ParsePosition; -import java.util.Map; - -public class NumberConverter extends DefaultTypeConverter { - - public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType) { - if (value instanceof String) { - if (toType == BigDecimal.class) { - return new BigDecimal((String) value); - } else if (toType == BigInteger.class) { - return new BigInteger((String) value); - } else if (toType.isPrimitive()) { - Object convertedValue = super.convertValue(context, value, toType); - String stringValue = (String) value; - if (!isInRange((Number) convertedValue, stringValue, toType)) - throw new XWorkException("Overflow or underflow casting: \"" + stringValue + "\" into class " + convertedValue.getClass().getName()); - - return convertedValue; - } else { - String stringValue = (String) value; - if (!toType.isPrimitive() && (stringValue == null || stringValue.length() == 0)) { - return null; - } - NumberFormat numFormat = NumberFormat.getInstance(getLocale(context)); - ParsePosition parsePos = new ParsePosition(0); - if (isIntegerType(toType)) { - numFormat.setParseIntegerOnly(true); - } - numFormat.setGroupingUsed(true); - Number number = numFormat.parse(stringValue, parsePos); - - if (parsePos.getIndex() != stringValue.length()) { - throw new XWorkException("Unparseable number: \"" + stringValue + "\" at position " - + parsePos.getIndex()); - } else { - if (!isInRange(number, stringValue, toType)) - throw new XWorkException("Overflow or underflow casting: \"" + stringValue + "\" into class " + number.getClass().getName()); - - value = super.convertValue(context, number, toType); - } - } - } else if (value instanceof Object[]) { - Object[] objArray = (Object[]) value; - - if (objArray.length == 1) { - return convertValue(context, null, null, null, objArray[0], toType); - } - } - - // pass it through DefaultTypeConverter - return super.convertValue(context, value, toType); - } - - protected boolean isInRange(Number value, String stringValue, Class toType) { - Number bigValue = null; - Number lowerBound = null; - Number upperBound = null; - - try { - if (double.class == toType || Double.class == toType) { - bigValue = new BigDecimal(stringValue); - // Double.MIN_VALUE is the smallest positive non-zero number - lowerBound = BigDecimal.valueOf(Double.MAX_VALUE).negate(); - upperBound = BigDecimal.valueOf(Double.MAX_VALUE); - } else if (float.class == toType || Float.class == toType) { - bigValue = new BigDecimal(stringValue); - // Float.MIN_VALUE is the smallest positive non-zero number - lowerBound = BigDecimal.valueOf(Float.MAX_VALUE).negate(); - upperBound = BigDecimal.valueOf(Float.MAX_VALUE); - } else if (byte.class == toType || Byte.class == toType) { - bigValue = new BigInteger(stringValue); - lowerBound = BigInteger.valueOf(Byte.MIN_VALUE); - upperBound = BigInteger.valueOf(Byte.MAX_VALUE); - } else if (char.class == toType || Character.class == toType) { - bigValue = new BigInteger(stringValue); - lowerBound = BigInteger.valueOf(Character.MIN_VALUE); - upperBound = BigInteger.valueOf(Character.MAX_VALUE); - } else if (short.class == toType || Short.class == toType) { - bigValue = new BigInteger(stringValue); - lowerBound = BigInteger.valueOf(Short.MIN_VALUE); - upperBound = BigInteger.valueOf(Short.MAX_VALUE); - } else if (int.class == toType || Integer.class == toType) { - bigValue = new BigInteger(stringValue); - lowerBound = BigInteger.valueOf(Integer.MIN_VALUE); - upperBound = BigInteger.valueOf(Integer.MAX_VALUE); - } else if (long.class == toType || Long.class == toType) { - bigValue = new BigInteger(stringValue); - lowerBound = BigInteger.valueOf(Long.MIN_VALUE); - upperBound = BigInteger.valueOf(Long.MAX_VALUE); - } else { - throw new IllegalArgumentException("Unexpected numeric type: " + toType.getName()); - } - } catch (NumberFormatException e) { - //shoult it fail here? BigInteger doesnt seem to be so nice parsing numbers as NumberFormat - return true; - } - - return ((Comparable)bigValue).compareTo(lowerBound) >= 0 && ((Comparable)bigValue).compareTo(upperBound) <= 0; - } - - private boolean isIntegerType(Class type) { - if (double.class == type || float.class == type || Double.class == type || Float.class == type - || char.class == type || Character.class == type) { - return false; - } - - return true; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/StringConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/StringConverter.java deleted file mode 100644 index 9c6cc8f185..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/StringConverter.java +++ /dev/null @@ -1,73 +0,0 @@ -package com.opensymphony.xwork2.conversion.impl; - -import org.apache.commons.lang3.StringUtils; - -import java.lang.reflect.Member; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.ArrayList; -import java.util.Date; -import java.util.List; -import java.util.Map; - -public class StringConverter extends DefaultTypeConverter { - - @Override - public Object convertValue(Map context, Object target, Member member, String propertyName, Object value, Class toType) { - String result = null; - - if (value instanceof int[]) { - int[] x = (int[]) value; - List intArray = new ArrayList<>(x.length); - - for (int aX : x) { - intArray.add(Integer.valueOf(aX)); - } - - result = StringUtils.join(intArray, ", "); - } else if (value instanceof long[]) { - long[] x = (long[]) value; - List longArray = new ArrayList<>(x.length); - - for (long aX : x) { - longArray.add(Long.valueOf(aX)); - } - - result = StringUtils.join(longArray, ", "); - } else if (value instanceof double[]) { - double[] x = (double[]) value; - List doubleArray = new ArrayList<>(x.length); - - for (double aX : x) { - doubleArray.add(new Double(aX)); - } - - result = StringUtils.join(doubleArray, ", "); - } else if (value instanceof boolean[]) { - boolean[] x = (boolean[]) value; - List booleanArray = new ArrayList<>(x.length); - - for (boolean aX : x) { - booleanArray.add(new Boolean(aX)); - } - - result = StringUtils.join(booleanArray, ", "); - } else if (value instanceof Date) { - DateFormat df = null; - if (value instanceof java.sql.Time) { - df = DateFormat.getTimeInstance(DateFormat.MEDIUM, getLocale(context)); - } else if (value instanceof java.sql.Timestamp) { - SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateTimeInstance(DateFormat.SHORT, - DateFormat.MEDIUM, - getLocale(context)); - df = new SimpleDateFormat(dfmt.toPattern() + MILLISECOND_FORMAT); - } else { - df = DateFormat.getDateInstance(DateFormat.SHORT, getLocale(context)); - } - result = df.format(value); - } else if (value instanceof String[]) { - result = StringUtils.join((String[]) value, ", "); - } - return result; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverter.java b/core/src/main/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverter.java deleted file mode 100644 index 8f4a74b82c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/impl/XWorkBasicConverter.java +++ /dev/null @@ -1,216 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.conversion.impl; - -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.XWorkException; -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; - -import java.lang.reflect.Member; -import java.util.Calendar; -import java.util.Collection; -import java.util.Date; -import java.util.Map; - - -/** - * - *

    - * XWork will automatically handle the most common type conversion for you. This includes support for converting to - * and from Strings for each of the following: - *

    - * - *
      - *
    • String
    • - *
    • boolean / Boolean
    • - *
    • char / Character
    • - *
    • int / Integer, float / Float, long / Long, double / Double
    • - *
    • dates - uses the SHORT format for the Locale associated with the current request
    • - *
    • arrays - assuming the individual strings can be coverted to the individual items
    • - *
    • collections - if not object type can be determined, it is assumed to be a String and a new ArrayList is - * created
    • - *
    - * - *

    Note that with arrays the type conversion will defer to the type of the array elements and try to convert each - * item individually. As with any other type conversion, if the conversion can't be performed the standard type - * conversion error reporting is used to indicate a problem occurred while processing the type conversion. - *

    - * - * - * - * @author Pat Lightbody - * @author Mike Mosiewicz - * @author Rainer Hermanns - * @author Alexandru Popescu - */ -public class XWorkBasicConverter extends DefaultTypeConverter { - - private Container container; - - @Inject - public void setContainer(Container container) { - this.container = container; - } - - @Override - public Object convertValue(Map context, Object o, Member member, String propertyName, Object value, Class toType) { - Object result = null; - - if (value == null || toType.isAssignableFrom(value.getClass())) { - // no need to convert at all, right? - return value; - } - - if (toType == String.class) { - /* the code below has been disabled as it causes sideffects in Struts2 (XW-512) - // if input (value) is a number then use special conversion method (XW-490) - Class inputType = value.getClass(); - if (Number.class.isAssignableFrom(inputType)) { - result = doConvertFromNumberToString(context, value, inputType); - if (result != null) { - return result; - } - }*/ - // okay use default string conversion - result = doConvertToString(context, value); - } else if (toType == boolean.class) { - result = doConvertToBoolean(value); - } else if (toType == Boolean.class) { - result = doConvertToBoolean(value); - } else if (toType.isArray()) { - result = doConvertToArray(context, o, member, propertyName, value, toType); - } else if (Date.class.isAssignableFrom(toType)) { - result = doConvertToDate(context, value, toType); - } else if (Calendar.class.isAssignableFrom(toType)) { - result = doConvertToCalendar(context, value); - } else if (Collection.class.isAssignableFrom(toType)) { - result = doConvertToCollection(context, o, member, propertyName, value, toType); - } else if (toType == Character.class) { - result = doConvertToCharacter(value); - } else if (toType == char.class) { - result = doConvertToCharacter(value); - } else if (Number.class.isAssignableFrom(toType) || toType.isPrimitive()) { - result = doConvertToNumber(context, value, toType); - } else if (toType == Class.class) { - result = doConvertToClass(value); - } - - if (result == null) { - if (value instanceof Object[]) { - Object[] array = (Object[]) value; - - if (array.length >= 1) { - value = array[0]; - } else { - value = null; - } - - // let's try to convert the first element only - result = convertValue(context, o, member, propertyName, value, toType); - } else if (!"".equals(value)) { // we've already tried the types we know - result = super.convertValue(context, value, toType); - } - - if (result == null && value != null && !"".equals(value)) { - throw new XWorkException("Cannot create type " + toType + " from value " + value); - } - } - - return result; - } - - private Object doConvertToCalendar(Map context, Object value) { - Object result = null; - Date dateResult = (Date) doConvertToDate(context, value, Date.class); - if (dateResult != null) { - Calendar calendar = Calendar.getInstance(); - calendar.setTime(dateResult); - result = calendar; - } - return result; - } - - private Object doConvertToCharacter(Object value) { - if (value instanceof String) { - String cStr = (String) value; - return (cStr.length() > 0) ? cStr.charAt(0) : null; - } - return null; - } - - private Object doConvertToBoolean(Object value) { - if (value instanceof String) { - String bStr = (String) value; - return Boolean.valueOf(bStr); - } - return null; - } - - private Class doConvertToClass(Object value) { - Class clazz = null; - if (value != null && value instanceof String && ((String) value).length() > 0) { - try { - clazz = Class.forName((String) value); - } catch (ClassNotFoundException e) { - throw new XWorkException(e.getLocalizedMessage(), e); - } - } - return clazz; - } - - private Object doConvertToCollection(Map context, Object o, Member member, String prop, Object value, Class toType) { - TypeConverter converter = container.getInstance(CollectionConverter.class); - if (converter == null) { - throw new XWorkException("TypeConverter with name [#0] must be registered first!", XWorkConstants.COLLECTION_CONVERTER); - } - return converter.convertValue(context, o, member, prop, value, toType); - } - - private Object doConvertToArray(Map context, Object o, Member member, String prop, Object value, Class toType) { - TypeConverter converter = container.getInstance(ArrayConverter.class); - if (converter == null) { - throw new XWorkException("TypeConverter with name [#0] must be registered first!", XWorkConstants.ARRAY_CONVERTER); - } - return converter.convertValue(context, o, member, prop, value, toType); - } - - private Object doConvertToDate(Map context, Object value, Class toType) { - TypeConverter converter = container.getInstance(DateConverter.class); - if (converter == null) { - throw new XWorkException("TypeConverter with name [#0] must be registered first!", XWorkConstants.DATE_CONVERTER); - } - return converter.convertValue(context, null, null, null, value, toType); - } - - private Object doConvertToNumber(Map context, Object value, Class toType) { - TypeConverter converter = container.getInstance(NumberConverter.class); - if (converter == null) { - throw new XWorkException("TypeConverter with name [#0] must be registered first!", XWorkConstants.NUMBER_CONVERTER); - } - return converter.convertValue(context, null, null, null, value, toType); - } - - private Object doConvertToString(Map context, Object value) { - TypeConverter converter = container.getInstance(StringConverter.class); - if (converter == null) { - throw new XWorkException("TypeConverter with name [#0] must be registered first!", XWorkConstants.STRING_CONVERTER); - } - return converter.convertValue(context, null, null, null, value, null); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/metadata/ConversionDescription.java b/core/src/main/java/com/opensymphony/xwork2/conversion/metadata/ConversionDescription.java deleted file mode 100644 index 3dc59dc225..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/metadata/ConversionDescription.java +++ /dev/null @@ -1,181 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.conversion.metadata; - -import com.opensymphony.xwork2.conversion.annotations.ConversionRule; -import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -import java.io.PrintWriter; -import java.io.StringWriter; - -/** - * ConversionDescription - * - * @author Rainer Hermanns - * @version $Id$ - */ -public class ConversionDescription { - - /** - * Jakarta commons-logging reference. - */ - protected static Logger log = null; - - - public static final String KEY_PREFIX = "Key_"; - public static final String ELEMENT_PREFIX = "Element_"; - public static final String KEY_PROPERTY_PREFIX = "KeyProperty_"; - public static final String DEPRECATED_ELEMENT_PREFIX = "Collection_"; - - /** - * Key used for type conversion of maps. - */ - String MAP_PREFIX = "Map_"; - - public String property; - public String typeConverter = ""; - public String rule = ""; - public String value = ""; - public String fullQualifiedClassName; - public String type = null; - - public ConversionDescription() { - log = LogManager.getLogger(this.getClass()); - } - - /** - * Creates an ConversionDescription with the specified property name. - * - * @param property property - */ - public ConversionDescription(String property) { - this.property = property; - log = LogManager.getLogger(this.getClass()); - } - - /** - *

    - * Sets the property name to be inserted into the related conversion.properties file.
    - * Note: Do not add COLLECTION_PREFIX or MAP_PREFIX keys to property names. - *

    - * - * @param property The property to be converted. - */ - public void setProperty(String property) { - this.property = property; - } - - /** - * Sets the class name of the type converter to be used. - * - * @param typeConverter The class name of the type converter. - */ - public void setTypeConverter(String typeConverter) { - this.typeConverter = typeConverter; - } - - /** - * @param rule the rule prefix for COLLECTION_PREFIX or MAP_PREFIX key. Defaults to en empty String. - */ - public void setRule(String rule) { - if (rule != null && rule.length() > 0) { - if (rule.equals(ConversionRule.COLLECTION.toString())) { - this.rule = DefaultObjectTypeDeterminer.DEPRECATED_ELEMENT_PREFIX; - } else if (rule.equals(ConversionRule.ELEMENT.toString())) { - this.rule = DefaultObjectTypeDeterminer.ELEMENT_PREFIX; - } else if (rule.equals(ConversionRule.KEY.toString())) { - this.rule = DefaultObjectTypeDeterminer.KEY_PREFIX; - } else if (rule.equals(ConversionRule.KEY_PROPERTY.toString())) { - this.rule = DefaultObjectTypeDeterminer.KEY_PROPERTY_PREFIX; - } else if (rule.equals(ConversionRule.MAP.toString())) { - this.rule = MAP_PREFIX; - } - } - } - - - public void setType(String type) { - this.type = type; - } - - public String getType() { - return type; - } - - public String getValue() { - return value; - } - - public void setValue(String value) { - this.value = value; - } - - /** - * Returns the conversion description as property entry. - *

    - * Example:
    - * property.name = converter.className
    - * Collection_property.name = converter.className
    - * Map_property.name = converter.className - * KeyProperty_name = id - *

    - * - * @return the conversion description as property entry. - */ - public String asProperty() { - StringWriter sw = new StringWriter(); - PrintWriter writer = null; - try { - writer = new PrintWriter(sw); - writer.print(rule); - writer.print(property); - writer.print("="); - if ( rule.startsWith(DefaultObjectTypeDeterminer.KEY_PROPERTY_PREFIX) && value != null && value.length() > 0 ) { - writer.print(value); - } else { - writer.print(typeConverter); - } - } finally { - if (writer != null) { - writer.flush(); - writer.close(); - } - } - - return sw.toString(); - - } - - /** - * Returns the fullQualifiedClassName attribute is used to create the special conversion.properties file name. - * - * @return full qualified class name - */ - public String getFullQualifiedClassName() { - return fullQualifiedClassName; - } - - /** - * The fullQualifiedClassName attribute is used to create the special conversion.properties file name. - * - * @param fullQualifiedClassName a full qualified class name - */ - public void setFullQualifiedClassName(String fullQualifiedClassName) { - this.fullQualifiedClassName = fullQualifiedClassName; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/conversion/metadata/package.html b/core/src/main/java/com/opensymphony/xwork2/conversion/metadata/package.html deleted file mode 100644 index c50a611ab9..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/conversion/metadata/package.html +++ /dev/null @@ -1 +0,0 @@ -Type conversion meta data classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/ActionFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/ActionFactory.java deleted file mode 100644 index 4cc41a9173..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/ActionFactory.java +++ /dev/null @@ -1,27 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.config.entities.ActionConfig; - -import java.util.Map; - -/** - * Used by {@link com.opensymphony.xwork2.ObjectFactory} to build actions - */ -public interface ActionFactory { - - /** - * Builds action instance - * - * @param actionName name of the action - * @param namespace namespace for the action - * @param config action config - * @param extraContext extra context map - * - * @return action object - * - * @throws Exception in case of any errors - */ - Object buildAction(String actionName, String namespace, ActionConfig config, Map extraContext) throws Exception; - -} - diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/ConverterFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/ConverterFactory.java deleted file mode 100644 index 81f1d4bf0c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/ConverterFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.conversion.TypeConverter; - -import java.util.Map; - -/** - * Dedicated interface used by {@link com.opensymphony.xwork2.ObjectFactory} to build {@link TypeConverter} - */ -public interface ConverterFactory { - - /** - * Build converter of given type - * - * @param converterClass to instantiate - * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext} - * - * @return instance of converterClass with inject dependencies - * - * @throws Exception in case of any errors - */ - TypeConverter buildConverter(Class converterClass, Map extraContext) throws Exception; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultActionFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/DefaultActionFactory.java deleted file mode 100644 index a17484a124..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultActionFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.inject.Inject; - -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultActionFactory implements ActionFactory { - - private ObjectFactory objectFactory; - - @Inject - public void setObjectFactory(ObjectFactory objectFactory) { - this.objectFactory = objectFactory; - } - - public Object buildAction(String actionName, String namespace, ActionConfig config, Map extraContext) throws Exception { - return objectFactory.buildBean(config.getClassName(), extraContext); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultConverterFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/DefaultConverterFactory.java deleted file mode 100644 index e35222e02e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultConverterFactory.java +++ /dev/null @@ -1,30 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultConverterFactory implements ConverterFactory { - - private static final Logger LOG = LogManager.getLogger(DefaultConverterFactory.class); - - private Container container; - - @Inject - public void setContainer(Container container) { - this.container = container; - } - - public TypeConverter buildConverter(Class converterClass, Map extraContext) throws Exception { - LOG.debug("Creating converter of type [{}]", converterClass.getCanonicalName()); - return container.getInstance(converterClass); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java deleted file mode 100644 index 3cdf6b553e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultInterceptorFactory.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.entities.InterceptorConfig; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.interceptor.Interceptor; -import com.opensymphony.xwork2.interceptor.WithLazyParams; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.HashMap; -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultInterceptorFactory implements InterceptorFactory { - - private static final Logger LOG = LogManager.getLogger(DefaultInterceptorFactory.class); - - private ObjectFactory objectFactory; - private ReflectionProvider reflectionProvider; - - @Inject - public void setObjectFactory(ObjectFactory objectFactory) { - this.objectFactory = objectFactory; - } - - @Inject - public void setReflectionProvider(ReflectionProvider reflectionProvider) { - this.reflectionProvider = reflectionProvider; - } - - public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams) throws ConfigurationException { - String interceptorClassName = interceptorConfig.getClassName(); - Map thisInterceptorClassParams = interceptorConfig.getParams(); - Map params = (thisInterceptorClassParams == null) ? new HashMap() : new HashMap<>(thisInterceptorClassParams); - params.putAll(interceptorRefParams); - - String message; - Throwable cause; - - try { - // interceptor instances are long-lived and used across user sessions, so don't try to pass in any extra context - Object o = objectFactory.buildBean(interceptorClassName, null); - if (o instanceof WithLazyParams) { - LOG.debug("Interceptor {} is marked with interface {} and params will be set during action invocation", - interceptorClassName, WithLazyParams.class.getName()); - } else { - reflectionProvider.setProperties(params, o); - } - - if (o instanceof Interceptor) { - Interceptor interceptor = (Interceptor) o; - interceptor.init(); - return interceptor; - } - - throw new ConfigurationException("Class [" + interceptorClassName + "] does not implement Interceptor", interceptorConfig); - } catch (InstantiationException e) { - cause = e; - message = "Unable to instantiate an instance of Interceptor class [" + interceptorClassName + "]."; - } catch (IllegalAccessException e) { - cause = e; - message = "IllegalAccessException while attempting to instantiate an instance of Interceptor class [" + interceptorClassName + "]."; - } catch (ClassCastException e) { - cause = e; - message = "Class [" + interceptorClassName + "] does not implement com.opensymphony.xwork2.interceptor.Interceptor"; - } catch (Exception e) { - cause = e; - message = "Caught Exception while registering Interceptor class " + interceptorClassName; - } catch (NoClassDefFoundError e) { - cause = e; - message = "Could not load class " + interceptorClassName + ". Perhaps it exists but certain dependencies are not available?"; - } - - throw new ConfigurationException(message, cause, interceptorConfig); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultResultFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/DefaultResultFactory.java deleted file mode 100644 index a5a6c79fe2..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultResultFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.Result; -import com.opensymphony.xwork2.config.entities.ResultConfig; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.reflection.ReflectionException; -import com.opensymphony.xwork2.util.reflection.ReflectionExceptionHandler; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; - -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultResultFactory implements ResultFactory { - - private ObjectFactory objectFactory; - private ReflectionProvider reflectionProvider; - - @Inject - public void setObjectFactory(ObjectFactory objectFactory) { - this.objectFactory = objectFactory; - } - - @Inject - public void setReflectionProvider(ReflectionProvider reflectionProvider) { - this.reflectionProvider = reflectionProvider; - } - - public Result buildResult(ResultConfig resultConfig, Map extraContext) throws Exception { - String resultClassName = resultConfig.getClassName(); - Result result = null; - - if (resultClassName != null) { - result = (Result) objectFactory.buildBean(resultClassName, extraContext); - Map params = resultConfig.getParams(); - if (params != null) { - for (Map.Entry paramEntry : params.entrySet()) { - try { - reflectionProvider.setProperty(paramEntry.getKey(), paramEntry.getValue(), result, extraContext, true); - } catch (ReflectionException ex) { - if (result instanceof ReflectionExceptionHandler) { - ((ReflectionExceptionHandler) result).handle(ex); - } - } - } - } - } - - return result; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultUnknownHandlerFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/DefaultUnknownHandlerFactory.java deleted file mode 100644 index 58fb339acf..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultUnknownHandlerFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.UnknownHandler; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; - -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultUnknownHandlerFactory implements UnknownHandlerFactory { - - private Container container; - - @Inject - public void setContainer(Container container) { - this.container = container; - } - - public UnknownHandler buildUnknownHandler(String unknownHandlerName, Map extraContext) throws Exception { - return container.getInstance(UnknownHandler.class, unknownHandlerName); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultValidatorFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/DefaultValidatorFactory.java deleted file mode 100644 index 8ce8b7753e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/DefaultValidatorFactory.java +++ /dev/null @@ -1,34 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; -import com.opensymphony.xwork2.validator.Validator; - -import java.util.Map; - -/** - * Default implementation - */ -public class DefaultValidatorFactory implements ValidatorFactory { - - private ObjectFactory objectFactory; - private ReflectionProvider reflectionProvider; - - @Inject - public void setObjectFactory(ObjectFactory objectFactory) { - this.objectFactory = objectFactory; - } - - @Inject - public void setReflectionProvider(ReflectionProvider reflectionProvider) { - this.reflectionProvider = reflectionProvider; - } - - public Validator buildValidator(String className, Map params, Map extraContext) throws Exception { - Validator validator = (Validator) objectFactory.buildBean(className, extraContext); - reflectionProvider.setProperties(params, validator, extraContext); - - return validator; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/InterceptorFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/InterceptorFactory.java deleted file mode 100644 index d12601c4db..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/InterceptorFactory.java +++ /dev/null @@ -1,32 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.entities.InterceptorConfig; -import com.opensymphony.xwork2.interceptor.Interceptor; - -import java.util.Map; - -/** - * Dedicated interface used by {@link com.opensymphony.xwork2.ObjectFactory} to build {@link com.opensymphony.xwork2.interceptor.Interceptor} - */ -public interface InterceptorFactory { - - /** - * Builds an Interceptor from the InterceptorConfig and the Map of - * parameters from the interceptor reference. Implementations of this method - * should ensure that the Interceptor is parameterized with both the - * parameters from the Interceptor config and the interceptor ref Map (the - * interceptor ref params take precedence), and that the Interceptor.init() - * method is called on the Interceptor instance before it is returned. - * - * @param interceptorConfig the InterceptorConfig from the configuration - * @param interceptorRefParams a Map of params provided in the Interceptor reference in the - * Action mapping or InterceptorStack definition - * - * @return interceptor - * - * @throws ConfigurationException in case of any configuration errors - */ - Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map interceptorRefParams) throws ConfigurationException; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/ResultFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/ResultFactory.java deleted file mode 100644 index c7191cb1bb..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/ResultFactory.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.Result; -import com.opensymphony.xwork2.config.entities.ResultConfig; - -import java.util.Map; - -/** - * Used by {@link com.opensymphony.xwork2.ObjectFactory} to build {@link com.opensymphony.xwork2.Result} - */ -public interface ResultFactory { - - Result buildResult(ResultConfig resultConfig, Map extraContext) throws Exception; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/UnknownHandlerFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/UnknownHandlerFactory.java deleted file mode 100644 index 9fe8687324..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/UnknownHandlerFactory.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.UnknownHandler; - -import java.util.Map; - -/** - * Dedicated interface used by {@link com.opensymphony.xwork2.ObjectFactory} to build {@link com.opensymphony.xwork2.UnknownHandler} - */ -public interface UnknownHandlerFactory { - - /** - * Builds unknown handler of given name - * - * @param unknownHandlerName name of unknown handler defined in struts.xml - * @param extraContext extra params - * - * @return instance of {@link com.opensymphony.xwork2.UnknownHandler} with injected dependencies - * - * @throws Exception in case of any errors - */ - UnknownHandler buildUnknownHandler(String unknownHandlerName, Map extraContext) throws Exception; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/factory/ValidatorFactory.java b/core/src/main/java/com/opensymphony/xwork2/factory/ValidatorFactory.java deleted file mode 100644 index f0beaa337d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/factory/ValidatorFactory.java +++ /dev/null @@ -1,25 +0,0 @@ -package com.opensymphony.xwork2.factory; - -import com.opensymphony.xwork2.validator.Validator; - -import java.util.Map; - -/** - * Dedicated interface used by {@link com.opensymphony.xwork2.ObjectFactory} to build {@link Validator} - */ -public interface ValidatorFactory { - - /** - * Build a Validator of the given type and set the parameters on it - * - * @param className the type of Validator to build - * @param params property name -> value Map to set onto the Validator instance - * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext} - * - * @return a validator instance - * - * @throws Exception in case of any errors - */ - Validator buildValidator(String className, Map params, Map extraContext) throws Exception; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/ConstructionContext.java b/core/src/main/java/com/opensymphony/xwork2/inject/ConstructionContext.java deleted file mode 100644 index d75d464937..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/inject/ConstructionContext.java +++ /dev/null @@ -1,119 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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. - */ - -package com.opensymphony.xwork2.inject; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; -import java.util.ArrayList; -import java.util.List; - -/** - * Context of a dependency construction. Used to manage circular references. - * - * @author crazybob@google.com (Bob Lee) - */ -class ConstructionContext { - - T currentReference; - boolean constructing; - - List> invocationHandlers; - - T getCurrentReference() { - return currentReference; - } - - void removeCurrentReference() { - this.currentReference = null; - } - - void setCurrentReference(T currentReference) { - this.currentReference = currentReference; - } - - boolean isConstructing() { - return constructing; - } - - void startConstruction() { - this.constructing = true; - } - - void finishConstruction() { - this.constructing = false; - invocationHandlers = null; - } - - Object createProxy(Class expectedType) { - // TODO: if I create a proxy which implements all the interfaces of - // the implementation type, I'll be able to get away with one proxy - // instance (as opposed to one per caller). - - if (!expectedType.isInterface()) { - throw new DependencyException(expectedType.getName() + " is not an interface."); - } - - if (invocationHandlers == null) { - invocationHandlers = new ArrayList>(); - } - - DelegatingInvocationHandler invocationHandler = new DelegatingInvocationHandler<>(); - invocationHandlers.add(invocationHandler); - - return Proxy.newProxyInstance( - expectedType.getClassLoader(), - new Class[] { expectedType }, - invocationHandler - ); - } - - void setProxyDelegates(T delegate) { - if (invocationHandlers != null) { - for (DelegatingInvocationHandler invocationHandler : invocationHandlers) { - invocationHandler.setDelegate(delegate); - } - } - } - - static class DelegatingInvocationHandler implements InvocationHandler { - - T delegate; - - public Object invoke(Object proxy, Method method, Object[] args) - throws Throwable { - if (delegate == null) { - throw new IllegalStateException( - "Not finished constructing. Please don't call methods on this" - + " object until the caller's construction is complete."); - } - - try { - return method.invoke(delegate, args); - } catch (IllegalAccessException | IllegalArgumentException e) { - throw new RuntimeException(e); - } catch (InvocationTargetException e) { - throw e.getTargetException(); - } - } - - void setDelegate(T delegate) { - this.delegate = delegate; - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java b/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java deleted file mode 100644 index 7e5ab62410..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/inject/ContainerImpl.java +++ /dev/null @@ -1,607 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - *

    - * 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. - *

    - */ - -package com.opensymphony.xwork2.inject; - -import com.opensymphony.xwork2.inject.util.ReferenceCache; - -import java.io.Serializable; -import java.lang.annotation.Annotation; -import java.lang.reflect.*; -import java.security.AccessControlException; -import java.util.*; -import java.util.Map.Entry; - -/** - * Default {@link Container} implementation. - * - * @author crazybob@google.com (Bob Lee) - * @see ContainerBuilder - */ -class ContainerImpl implements Container { - - final Map, InternalFactory> factories; - final Map, Set> factoryNamesByType; - - ContainerImpl(Map, InternalFactory> factories) { - this.factories = factories; - Map, Set> map = new HashMap<>(); - for (Key key : factories.keySet()) { - Set names = map.get(key.getType()); - if (names == null) { - names = new HashSet<>(); - map.put(key.getType(), names); - } - names.add(key.getName()); - } - - for (Entry, Set> entry : map.entrySet()) { - entry.setValue(Collections.unmodifiableSet(entry.getValue())); - } - - this.factoryNamesByType = Collections.unmodifiableMap(map); - } - - @SuppressWarnings("unchecked") - InternalFactory getFactory(Key key) { - return (InternalFactory) factories.get(key); - } - - /** - * Field and method injectors. - */ - final Map, List> injectors = - new ReferenceCache, List>() { - @Override - protected List create(Class key) { - List injectors = new ArrayList<>(); - addInjectors(key, injectors); - return injectors; - } - }; - - /** - * Recursively adds injectors for fields and methods from the given class to the given list. Injects parent classes - * before sub classes. - */ - void addInjectors(Class clazz, List injectors) { - if (clazz == Object.class) { - return; - } - - // Add injectors for superclass first. - addInjectors(clazz.getSuperclass(), injectors); - - // TODO (crazybob): Filter out overridden members. - addInjectorsForFields(clazz.getDeclaredFields(), false, injectors); - addInjectorsForMethods(clazz.getDeclaredMethods(), false, injectors); - } - - void injectStatics(List> staticInjections) { - final List injectors = new ArrayList<>(); - - for (Class clazz : staticInjections) { - addInjectorsForFields(clazz.getDeclaredFields(), true, injectors); - addInjectorsForMethods(clazz.getDeclaredMethods(), true, injectors); - } - - callInContext(new ContextualCallable() { - public Void call(InternalContext context) { - for (Injector injector : injectors) { - injector.inject(context, null); - } - return null; - } - }); - } - - void addInjectorsForMethods(Method[] methods, boolean statics, List injectors) { - addInjectorsForMembers(Arrays.asList(methods), statics, injectors, - new InjectorFactory() { - public Injector create(ContainerImpl container, Method method, - String name) throws MissingDependencyException { - return new MethodInjector(container, method, name); - } - }); - } - - void addInjectorsForFields(Field[] fields, boolean statics, List injectors) { - addInjectorsForMembers(Arrays.asList(fields), statics, injectors, - new InjectorFactory() { - public Injector create(ContainerImpl container, Field field, - String name) throws MissingDependencyException { - return new FieldInjector(container, field, name); - } - }); - } - - void addInjectorsForMembers( - List members, boolean statics, List injectors, InjectorFactory injectorFactory) { - for (M member : members) { - if (isStatic(member) == statics) { - Inject inject = member.getAnnotation(Inject.class); - if (inject != null) { - try { - injectors.add(injectorFactory.create(this, member, inject.value())); - } catch (MissingDependencyException e) { - if (inject.required()) { - throw new DependencyException(e); - } - } - } - } - } - } - - interface InjectorFactory { - - Injector create(ContainerImpl container, M member, String name) - throws MissingDependencyException; - } - - private boolean isStatic(Member member) { - return Modifier.isStatic(member.getModifiers()); - } - - static class FieldInjector implements Injector { - - final Field field; - final InternalFactory factory; - final ExternalContext externalContext; - - public FieldInjector(ContainerImpl container, Field field, String name) - throws MissingDependencyException { - this.field = field; - if (!field.isAccessible()) { - SecurityManager sm = System.getSecurityManager(); - try { - if (sm != null) { - sm.checkPermission(new ReflectPermission("suppressAccessChecks")); - } - field.setAccessible(true); - } catch (AccessControlException e) { - throw new DependencyException("Security manager in use, could not access field: " - + field.getDeclaringClass().getName() + "(" + field.getName() + ")", e); - } - } - - Key key = Key.newInstance(field.getType(), name); - factory = container.getFactory(key); - if (factory == null) { - throw new MissingDependencyException("No mapping found for dependency " + key + " in " + field + "."); - } - - this.externalContext = ExternalContext.newInstance(field, key, container); - } - - public void inject(InternalContext context, Object o) { - ExternalContext previous = context.getExternalContext(); - context.setExternalContext(externalContext); - try { - field.set(o, factory.create(context)); - } catch (IllegalAccessException e) { - throw new AssertionError(e); - } finally { - context.setExternalContext(previous); - } - } - } - - /** - * Gets parameter injectors. - * - * @param member to which the parameters belong - * @param annotations on the parameters - * @param parameterTypes parameter types - * @return injections - */ - ParameterInjector[] - getParametersInjectors(M member, Annotation[][] annotations, Class[] parameterTypes, String defaultName) throws MissingDependencyException { - List> parameterInjectors = new ArrayList<>(); - - Iterator annotationsIterator = Arrays.asList(annotations).iterator(); - for (Class parameterType : parameterTypes) { - Inject annotation = findInject(annotationsIterator.next()); - String name = annotation == null ? defaultName : annotation.value(); - Key key = Key.newInstance(parameterType, name); - parameterInjectors.add(createParameterInjector(key, member)); - } - - return toArray(parameterInjectors); - } - - ParameterInjector createParameterInjector(Key key, Member member) throws MissingDependencyException { - InternalFactory factory = getFactory(key); - if (factory == null) { - throw new MissingDependencyException("No mapping found for dependency " + key + " in " + member + "."); - } - - ExternalContext externalContext = ExternalContext.newInstance(member, key, this); - return new ParameterInjector(externalContext, factory); - } - - @SuppressWarnings("unchecked") - private ParameterInjector[] toArray(List> parameterInjections) { - return parameterInjections.toArray(new ParameterInjector[parameterInjections.size()]); - } - - /** - * Finds the {@link Inject} annotation in an array of annotations. - */ - Inject findInject(Annotation[] annotations) { - for (Annotation annotation : annotations) { - if (annotation.annotationType() == Inject.class) { - return Inject.class.cast(annotation); - } - } - return null; - } - - static class MethodInjector implements Injector { - - final Method method; - final ParameterInjector[] parameterInjectors; - - public MethodInjector(ContainerImpl container, Method method, String name) throws MissingDependencyException { - this.method = method; - if (!method.isAccessible()) { - SecurityManager sm = System.getSecurityManager(); - try { - if (sm != null) { - sm.checkPermission(new ReflectPermission("suppressAccessChecks")); - } - method.setAccessible(true); - } catch (AccessControlException e) { - throw new DependencyException("Security manager in use, could not access method: " - + name + "(" + method.getName() + ")", e); - } - } - - Class[] parameterTypes = method.getParameterTypes(); - if (parameterTypes.length == 0) { - throw new DependencyException(method + " has no parameters to inject."); - } - parameterInjectors = container.getParametersInjectors( - method, method.getParameterAnnotations(), parameterTypes, name); - } - - public void inject(InternalContext context, Object o) { - try { - method.invoke(o, getParameters(method, context, parameterInjectors)); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - } - - Map, ConstructorInjector> constructors = - new ReferenceCache, ConstructorInjector>() { - @Override - @SuppressWarnings("unchecked") - protected ConstructorInjector create(Class implementation) { - return new ConstructorInjector(ContainerImpl.this, implementation); - } - }; - - static class ConstructorInjector { - - final Class implementation; - final List injectors; - final Constructor constructor; - final ParameterInjector[] parameterInjectors; - - ConstructorInjector(ContainerImpl container, Class implementation) { - this.implementation = implementation; - - constructor = findConstructorIn(implementation); - if (!constructor.isAccessible()) { - SecurityManager sm = System.getSecurityManager(); - try { - if (sm != null) { - sm.checkPermission(new ReflectPermission("suppressAccessChecks")); - } - constructor.setAccessible(true); - } catch (AccessControlException e) { - throw new DependencyException("Security manager in use, could not access constructor: " - + implementation.getName() + "(" + constructor.getName() + ")", e); - } - } - - MissingDependencyException exception = null; - Inject inject = null; - ParameterInjector[] parameters = null; - - try { - inject = constructor.getAnnotation(Inject.class); - parameters = constructParameterInjector(inject, container, constructor); - } catch (MissingDependencyException e) { - exception = e; - } - parameterInjectors = parameters; - - if (exception != null) { - if (inject != null && inject.required()) { - throw new DependencyException(exception); - } - } - injectors = container.injectors.get(implementation); - } - - ParameterInjector[] constructParameterInjector( - Inject inject, ContainerImpl container, Constructor constructor) throws MissingDependencyException { - return constructor.getParameterTypes().length == 0 - ? null // default constructor. - : container.getParametersInjectors( - constructor, - constructor.getParameterAnnotations(), - constructor.getParameterTypes(), - inject.value() - ); - } - - @SuppressWarnings("unchecked") - private Constructor findConstructorIn(Class implementation) { - Constructor found = null; - Constructor[] declaredConstructors = (Constructor[]) implementation.getDeclaredConstructors(); - for (Constructor constructor : declaredConstructors) { - if (constructor.getAnnotation(Inject.class) != null) { - if (found != null) { - throw new DependencyException("More than one constructor annotated" - + " with @Inject found in " + implementation + "."); - } - found = constructor; - } - } - if (found != null) { - return found; - } - - // If no annotated constructor is found, look for a no-arg constructor - // instead. - try { - return implementation.getDeclaredConstructor(); - } catch (NoSuchMethodException e) { - throw new DependencyException("Could not find a suitable constructor in " + implementation.getName() + "."); - } - } - - /** - * Construct an instance. Returns {@code Object} instead of {@code T} because it may return a proxy. - */ - Object construct(InternalContext context, Class expectedType) { - ConstructionContext constructionContext = context.getConstructionContext(this); - - // We have a circular reference between constructors. Return a proxy. - if (constructionContext.isConstructing()) { - // TODO (crazybob): if we can't proxy this object, can we proxy the - // other object? - return constructionContext.createProxy(expectedType); - } - - // If we're re-entering this factory while injecting fields or methods, - // return the same instance. This prevents infinite loops. - T t = constructionContext.getCurrentReference(); - if (t != null) { - return t; - } - - try { - // First time through... - constructionContext.startConstruction(); - try { - Object[] parameters = getParameters(constructor, context, parameterInjectors); - t = constructor.newInstance(parameters); - constructionContext.setProxyDelegates(t); - } finally { - constructionContext.finishConstruction(); - } - - // Store reference. If an injector re-enters this factory, they'll - // get the same reference. - constructionContext.setCurrentReference(t); - - // Inject fields and methods. - for (Injector injector : injectors) { - injector.inject(context, t); - } - - return t; - } catch (InstantiationException | IllegalAccessException | InvocationTargetException e) { - throw new RuntimeException(e); - } finally { - constructionContext.removeCurrentReference(); - } - } - } - - static class ParameterInjector { - - final ExternalContext externalContext; - final InternalFactory factory; - - public ParameterInjector(ExternalContext externalContext, InternalFactory factory) { - this.externalContext = externalContext; - this.factory = factory; - } - - T inject(Member member, InternalContext context) { - ExternalContext previous = context.getExternalContext(); - context.setExternalContext(externalContext); - try { - return factory.create(context); - } finally { - context.setExternalContext(previous); - } - } - } - - private static Object[] getParameters(Member member, InternalContext context, ParameterInjector[] parameterInjectors) { - if (parameterInjectors == null) { - return null; - } - - Object[] parameters = new Object[parameterInjectors.length]; - for (int i = 0; i < parameters.length; i++) { - parameters[i] = parameterInjectors[i].inject(member, context); - } - return parameters; - } - - void inject(Object o, InternalContext context) { - List injectors = this.injectors.get(o.getClass()); - for (Injector injector : injectors) { - injector.inject(context, o); - } - } - - T inject(Class implementation, InternalContext context) { - try { - ConstructorInjector constructor = getConstructor(implementation); - return implementation.cast(constructor.construct(context, implementation)); - } catch (Exception e) { - throw new RuntimeException(e); - } - } - - @SuppressWarnings("unchecked") - T getInstance(Class type, String name, InternalContext context) { - ExternalContext previous = context.getExternalContext(); - Key key = Key.newInstance(type, name); - context.setExternalContext(ExternalContext.newInstance(null, key, this)); - try { - InternalFactory o = getFactory(key); - if (o != null) { - return getFactory(key).create(context); - } else { - return null; - } - } finally { - context.setExternalContext(previous); - } - } - - T getInstance(Class type, InternalContext context) { - return getInstance(type, DEFAULT_NAME, context); - } - - public void inject(final Object o) { - callInContext(new ContextualCallable() { - public Void call(InternalContext context) { - inject(o, context); - return null; - } - }); - } - - public T inject(final Class implementation) { - return callInContext(new ContextualCallable() { - public T call(InternalContext context) { - return inject(implementation, context); - } - }); - } - - public T getInstance(final Class type, final String name) { - return callInContext(new ContextualCallable() { - public T call(InternalContext context) { - return getInstance(type, name, context); - } - }); - } - - public T getInstance(final Class type) { - return callInContext(new ContextualCallable() { - public T call(InternalContext context) { - return getInstance(type, context); - } - }); - } - - public Set getInstanceNames(final Class type) { - Set names = factoryNamesByType.get(type); - if (names == null) { - names = Collections.emptySet(); - } - return names; - } - - ThreadLocal localContext = new ThreadLocal() { - @Override - protected Object[] initialValue() { - return new Object[1]; - } - }; - - /** - * Looks up thread local context. Creates (and removes) a new context if necessary. - */ - T callInContext(ContextualCallable callable) { - Object[] reference = localContext.get(); - if (reference[0] == null) { - reference[0] = new InternalContext(this); - try { - return callable.call((InternalContext) reference[0]); - } finally { - // Only remove the context if this call created it. - reference[0] = null; - // WW-3768: ThreadLocal was not removed - localContext.remove(); - } - } else { - // Someone else will clean up this context. - return callable.call((InternalContext) reference[0]); - } - } - - interface ContextualCallable { - T call(InternalContext context); - } - - /** - * Gets a constructor function for a given implementation class. - */ - @SuppressWarnings("unchecked") - ConstructorInjector getConstructor(Class implementation) { - return constructors.get(implementation); - } - - final ThreadLocal localScopeStrategy = new ThreadLocal<>(); - - public void setScopeStrategy(Scope.Strategy scopeStrategy) { - this.localScopeStrategy.set(scopeStrategy); - } - - public void removeScopeStrategy() { - this.localScopeStrategy.remove(); - } - - /** - * Injects a field or method in a given object. - */ - interface Injector extends Serializable { - void inject(InternalContext context, Object o); - } - - static class MissingDependencyException extends Exception { - MissingDependencyException(String message) { - super(message); - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/Factory.java b/core/src/main/java/com/opensymphony/xwork2/inject/Factory.java deleted file mode 100644 index 11175061e1..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/inject/Factory.java +++ /dev/null @@ -1,34 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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. - */ - -package com.opensymphony.xwork2.inject; - -/** - * A custom factory. Creates objects which will be injected. - * - * @author crazybob@google.com (Bob Lee) - */ -public interface Factory { - - /** - * Creates an object to be injected. - * - * @param context of this injection - * @return instance to be injected - * @throws Exception if unable to create object - */ - T create(Context context) throws Exception; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/Inject.java b/core/src/main/java/com/opensymphony/xwork2/inject/Inject.java deleted file mode 100644 index 2e45761ed2..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/inject/Inject.java +++ /dev/null @@ -1,47 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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. - */ - -package com.opensymphony.xwork2.inject; - -import static com.opensymphony.xwork2.inject.Container.DEFAULT_NAME; - -import static java.lang.annotation.ElementType.*; -import java.lang.annotation.Retention; -import static java.lang.annotation.RetentionPolicy.RUNTIME; -import java.lang.annotation.Target; - -/** - *

    Annotates members and parameters which should have their value[s] - * injected. - *

    - * - * @author crazybob@google.com (Bob Lee) - */ -@Target({METHOD, CONSTRUCTOR, FIELD, PARAMETER}) -@Retention(RUNTIME) -public @interface Inject { - - /** - * @return Dependency name. Defaults to {@link Container#DEFAULT_NAME}. - */ - String value() default DEFAULT_NAME; - - /** - * @return Whether or not injection is required. Applicable only to methods and - * fields (not constructors or parameters). - */ - boolean required() default true; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/InternalContext.java b/core/src/main/java/com/opensymphony/xwork2/inject/InternalContext.java deleted file mode 100644 index 7014480bd0..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/inject/InternalContext.java +++ /dev/null @@ -1,77 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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. - */ - -package com.opensymphony.xwork2.inject; - -import java.util.HashMap; -import java.util.Map; - -/** - * Internal context. Used to coordinate injections and support circular - * dependencies. - * - * @author crazybob@google.com (Bob Lee) - */ -class InternalContext { - - final ContainerImpl container; - final Map> constructionContexts = new HashMap>(); - Scope.Strategy scopeStrategy; - ExternalContext externalContext; - - InternalContext(ContainerImpl container) { - this.container = container; - } - - public Container getContainer() { - return container; - } - - ContainerImpl getContainerImpl() { - return container; - } - - Scope.Strategy getScopeStrategy() { - if (scopeStrategy == null) { - scopeStrategy = (Scope.Strategy) container.localScopeStrategy.get(); - - if (scopeStrategy == null) { - throw new IllegalStateException("Scope strategy not set. Please call Container.setScopeStrategy()."); - } - } - - return scopeStrategy; - } - - @SuppressWarnings("unchecked") - ConstructionContext getConstructionContext(Object key) { - ConstructionContext constructionContext = (ConstructionContext) constructionContexts.get(key); - if (constructionContext == null) { - constructionContext = new ConstructionContext(); - constructionContexts.put(key, constructionContext); - } - return constructionContext; - } - - @SuppressWarnings("unchecked") - ExternalContext getExternalContext() { - return (ExternalContext) externalContext; - } - - void setExternalContext(ExternalContext externalContext) { - this.externalContext = externalContext; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java b/core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java deleted file mode 100644 index 49fcf27e89..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/inject/InternalFactory.java +++ /dev/null @@ -1,35 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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. - */ - -package com.opensymphony.xwork2.inject; - -import java.io.Serializable; - -/** - * Creates objects which will be injected. - * - * @author crazybob@google.com (Bob Lee) - */ -interface InternalFactory extends Serializable { - - /** - * Creates an object to be injected. - * - * @param context of this injection - * @return instance to be injected - */ - T create(InternalContext context); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/Key.java b/core/src/main/java/com/opensymphony/xwork2/inject/Key.java deleted file mode 100644 index 4c05a383d2..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/inject/Key.java +++ /dev/null @@ -1,81 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - *

    - * 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. - *

    - */ - -package com.opensymphony.xwork2.inject; - -/** - * Dependency mapping key. Uniquely identified by the required type and name. - * - * @author crazybob@google.com (Bob Lee) - */ -class Key { - - final Class type; - final String name; - final int hashCode; - - private Key(Class type, String name) { - if (type == null) { - throw new NullPointerException("Type is null."); - } - if (name == null) { - throw new NullPointerException("Name is null."); - } - - this.type = type; - this.name = name; - - hashCode = type.hashCode() * 31 + name.hashCode(); - } - - Class getType() { - return type; - } - - String getName() { - return name; - } - - @Override - public int hashCode() { - return hashCode; - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof Key)) { - return false; - } - if (o == this) { - return true; - } - Key other = (Key) o; - return name.equals(other.name) && type.equals(other.type); - } - - @Override - public String toString() { - return "[type=" + type.getName() + ", name='" + name + "']"; - } - - static Key newInstance(Class type, String name) { - return new Key(type, name); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/package-info.java b/core/src/main/java/com/opensymphony/xwork2/inject/package-info.java deleted file mode 100644 index 6e26e24c55..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/inject/package-info.java +++ /dev/null @@ -1,30 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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. - */ - -/** - * Guice (pronounced "juice"). A lightweight dependency injection - * container. Features include: - * - *
      - *
    • constructor, method, and field injection
    • - *
    • static method and field injection
    • - *
    • circular reference support (including constructors if you depend upon - * interfaces)
    • - *
    • high performance
    • - *
    • externalize what needs to be and no more
    • - *
    - */ -package com.opensymphony.xwork2.inject; diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/util/Strings.java b/core/src/main/java/com/opensymphony/xwork2/inject/util/Strings.java deleted file mode 100644 index a15291ae2c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/inject/util/Strings.java +++ /dev/null @@ -1,55 +0,0 @@ -/** - * Copyright (C) 2006 Google Inc. - * - * 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. - */ - -package com.opensymphony.xwork2.inject.util; - -/** - * String utilities. - * - * @author crazybob@google.com (Bob Lee) - */ -public class Strings { - - /** - * Returns a string that is equivalent to the specified string with its - * first character converted to uppercase as by {@link String#toUpperCase}. - * The returned string will have the same value as the specified string if - * its first character is non-alphabetic, if its first character is already - * uppercase, or if the specified string is of length 0. - * - *

    For example: - *

    -   *    capitalize("foo bar").equals("Foo bar");
    -   *    capitalize("2b or not 2b").equals("2b or not 2b")
    -   *    capitalize("Foo bar").equals("Foo bar");
    -   *    capitalize("").equals("");
    -   * 
    - * - * @param s the string whose first character is to be uppercased - * @return a string equivalent to s with its first character - * converted to uppercase - * @throws NullPointerException if s is null - */ - public static String capitalize(String s) { - if (s.length() == 0) - return s; - char first = s.charAt(0); - char capitalized = Character.toUpperCase(first); - return (first == capitalized) - ? s - : capitalized + s.substring(1); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/inject/util/package.html b/core/src/main/java/com/opensymphony/xwork2/inject/util/package.html deleted file mode 100644 index e3264616f4..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/inject/util/package.html +++ /dev/null @@ -1 +0,0 @@ -Guice util classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java deleted file mode 100644 index 470d349509..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/AbstractInterceptor.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionInvocation; - -/** - * Provides default implementations of optional lifecycle methods - */ -public abstract class AbstractInterceptor implements Interceptor { - - /** - * Does nothing - */ - public void init() { - } - - /** - * Does nothing - */ - public void destroy() { - } - - - /** - * Override to handle interception - */ - public abstract String intercept(ActionInvocation invocation) throws Exception; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java deleted file mode 100644 index b82b773195..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/AliasInterceptor.java +++ /dev/null @@ -1,204 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ClearableValueStack; -import com.opensymphony.xwork2.util.Evaluated; -import com.opensymphony.xwork2.LocalizedTextProvider; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.util.ValueStackFactory; -import com.opensymphony.xwork2.util.reflection.ReflectionContextState; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.struts2.dispatcher.HttpParameters; - -import java.util.Map; - - -/** - * - * - * The aim of this Interceptor is to alias a named parameter to a different named parameter. By acting as the glue - * between actions sharing similar parameters (but with different names), it can help greatly with action chaining. - * - *

    Action's alias expressions should be in the form of #{ "name1" : "alias1", "name2" : "alias2" }. - * This means that assuming an action (or something else in the stack) has a value for the expression named name1 and the - * action this interceptor is applied to has a setter named alias1, alias1 will be set with the value from - * name1. - *

    - * - * - * - *

    Interceptor parameters:

    - * - * - * - *
      - * - *
    • aliasesKey (optional) - the name of the action parameter to look for the alias map (by default this is - * aliases).
    • - * - *
    - * - * - * - *

    Extending the interceptor:

    - * - * - * - * This interceptor does not have any known extension points. - * - * - * - *

    Example code:

    - * - *
    - * 
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <!-- The value for the foo parameter will be applied as if it were named bar -->
    - *     <param name="aliases">#{ 'foo' : 'bar' }</param>
    - *
    - *     <interceptor-ref name="alias"/>
    - *     <interceptor-ref name="basicStack"/>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - * 
    - * 
    - * - * @author Matthew Payne - */ -public class AliasInterceptor extends AbstractInterceptor { - - private static final Logger LOG = LogManager.getLogger(AliasInterceptor.class); - - private static final String DEFAULT_ALIAS_KEY = "aliases"; - protected String aliasesKey = DEFAULT_ALIAS_KEY; - - protected ValueStackFactory valueStackFactory; - protected LocalizedTextProvider localizedTextProvider; - protected boolean devMode = false; - - @Inject(XWorkConstants.DEV_MODE) - public void setDevMode(String mode) { - this.devMode = Boolean.parseBoolean(mode); - } - - @Inject - public void setValueStackFactory(ValueStackFactory valueStackFactory) { - this.valueStackFactory = valueStackFactory; - } - - @Inject - public void setLocalizedTextProvider(LocalizedTextProvider localizedTextProvider) { - this.localizedTextProvider = localizedTextProvider; - } - - /** - *

    - * Sets the name of the action parameter to look for the alias map. - *

    - * - *

    - * Default is aliases. - *

    - * - * @param aliasesKey the name of the action parameter - */ - public void setAliasesKey(String aliasesKey) { - this.aliasesKey = aliasesKey; - } - - @Override public String intercept(ActionInvocation invocation) throws Exception { - - ActionConfig config = invocation.getProxy().getConfig(); - ActionContext ac = invocation.getInvocationContext(); - Object action = invocation.getAction(); - - // get the action's parameters - final Map parameters = config.getParams(); - - if (parameters.containsKey(aliasesKey)) { - - String aliasExpression = parameters.get(aliasesKey); - ValueStack stack = ac.getValueStack(); - Object obj = stack.findValue(aliasExpression); - - if (obj != null && obj instanceof Map) { - //get secure stack - ValueStack newStack = valueStackFactory.createValueStack(stack); - boolean clearableStack = newStack instanceof ClearableValueStack; - if (clearableStack) { - //if the stack's context can be cleared, do that to prevent OGNL - //from having access to objects in the stack, see XW-641 - ((ClearableValueStack)newStack).clearContextValues(); - Map context = newStack.getContext(); - ReflectionContextState.setCreatingNullObjects(context, true); - ReflectionContextState.setDenyMethodExecution(context, true); - ReflectionContextState.setReportingConversionErrors(context, true); - - //keep locale from original context - context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE)); - } - - // override - Map aliases = (Map) obj; - for (Object o : aliases.entrySet()) { - Map.Entry entry = (Map.Entry) o; - String name = entry.getKey().toString(); - String alias = (String) entry.getValue(); - Evaluated value = new Evaluated(stack.findValue(name)); - if (!value.isDefined()) { - // workaround - HttpParameters contextParameters = ActionContext.getContext().getParameters(); - - if (null != contextParameters) { - value = new Evaluated(contextParameters.get(name)); - } - } - if (value.isDefined()) { - try { - newStack.setValue(alias, value.get()); - } catch (RuntimeException e) { - if (devMode) { - String developerNotification = localizedTextProvider.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{ - "Unexpected Exception caught setting '" + entry.getKey() + "' on '" + action.getClass() + ": " + e.getMessage() - }); - LOG.error(developerNotification); - if (action instanceof ValidationAware) { - ((ValidationAware) action).addActionMessage(developerNotification); - } - } - } - } - } - - if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null)) - stack.getContext().put(ActionContext.CONVERSION_ERRORS, newStack.getContext().get(ActionContext.CONVERSION_ERRORS)); - } else { - LOG.debug("invalid alias expression: {}", aliasesKey); - } - } - - return invocation.invoke(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java deleted file mode 100644 index 27a0f6861f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ChainingInterceptor.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionChainResult; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.Result; -import com.opensymphony.xwork2.Unchainable; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.CompoundRoot; -import com.opensymphony.xwork2.util.TextParseUtil; -import com.opensymphony.xwork2.util.ValueStack; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; - -import java.util.*; - - -/** - * - *

    - * An interceptor that copies all the properties of every object in the value stack to the currently executing object, - * except for any object that implements {@link Unchainable}. A collection of optional includes and - * excludes may be provided to control how and which parameters are copied. Only includes or excludes may be - * specified. Specifying both results in undefined behavior. See the javadocs for {@link ReflectionProvider#copy(Object, Object, - * java.util.Map, java.util.Collection, java.util.Collection)} for more information. - *

    - * - *

    - * Note: It is important to remember that this interceptor does nothing if there are no objects already on the stack. - *
    This means two things: - *
    One, you can safely apply it to all your actions without any worry of adverse affects. - *
    Two, it is up to you to ensure an object exists in the stack prior to invoking this action. The most typical way this is done - * is through the use of the chain result type, which combines with this interceptor to make up the action - * chaining feature. - *

    - * - *

    - * Note: By default Errors, Field errors and Message aren't copied during chaining, to change the behaviour you can specify - * the below three constants in struts.properties or struts.xml: - *

    - * - *
      - *
    • struts.xwork.chaining.copyErrors - set to true to copy Action Errors
    • - *
    • struts.xwork.chaining.copyFieldErrors - set to true to copy Field Errors
    • - *
    • struts.xwork.chaining.copyMessages - set to true to copy Action Messages
    • - *
    - * - *

    - * Example: - *

    - * - *
    - * <constant name="struts.xwork.chaining.copyErrors" value="true"/>
    - * 
    - * - *

    - * Note: By default actionErrors and actionMessages are excluded when copping object's properties. - *

    - * - * Interceptor parameters: - * - *
      - *
    • excludes (optional) - the list of parameter names to exclude from copying (all others will be included).
    • - *
    • includes (optional) - the list of parameter names to include when copying (all others will be excluded).
    • - *
    - * - * Extending the interceptor: - * - *

    - * There are no known extension points to this interceptor. - *

    - * - * Example code: - * - * - *
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <interceptor-ref name="basicStack"/>
    - *     <result name="success" type="chain">otherAction</result>
    - * </action>
    - * 
    - * - *
    - * <action name="otherAction" class="com.examples.OtherAction">
    - *     <interceptor-ref name="chain"/>
    - *     <interceptor-ref name="basicStack"/>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - * 
    - * - * - * - * @author mrdon - * @author tm_jee ( tm_jee(at)yahoo.co.uk ) - * @see com.opensymphony.xwork2.ActionChainResult - */ -public class ChainingInterceptor extends AbstractInterceptor { - - private static final Logger LOG = LogManager.getLogger(ChainingInterceptor.class); - - private static final String ACTION_ERRORS = "actionErrors"; - private static final String FIELD_ERRORS = "fieldErrors"; - private static final String ACTION_MESSAGES = "actionMessages"; - - private boolean copyMessages = false; - private boolean copyErrors = false; - private boolean copyFieldErrors = false; - - protected Collection excludes; - - protected Collection includes; - protected ReflectionProvider reflectionProvider; - - @Inject - public void setReflectionProvider(ReflectionProvider prov) { - this.reflectionProvider = prov; - } - - @Inject(value = "struts.xwork.chaining.copyErrors", required = false) - public void setCopyErrors(String copyErrors) { - this.copyErrors = "true".equalsIgnoreCase(copyErrors); - } - - @Inject(value = "struts.xwork.chaining.copyFieldErrors", required = false) - public void setCopyFieldErrors(String copyFieldErrors) { - this.copyFieldErrors = "true".equalsIgnoreCase(copyFieldErrors); - } - - @Inject(value = "struts.xwork.chaining.copyMessages", required = false) - public void setCopyMessages(String copyMessages) { - this.copyMessages = "true".equalsIgnoreCase(copyMessages); - } - - @Override - public String intercept(ActionInvocation invocation) throws Exception { - ValueStack stack = invocation.getStack(); - CompoundRoot root = stack.getRoot(); - if (shouldCopyStack(invocation, root)) { - copyStack(invocation, root); - } - return invocation.invoke(); - } - - private void copyStack(ActionInvocation invocation, CompoundRoot root) { - List list = prepareList(root); - Map ctxMap = invocation.getInvocationContext().getContextMap(); - for (Object object : list) { - if (shouldCopy(object)) { - reflectionProvider.copy(object, invocation.getAction(), ctxMap, prepareExcludes(), includes); - } - } - } - - private Collection prepareExcludes() { - Collection localExcludes = excludes; - if (!copyErrors || !copyMessages ||!copyFieldErrors) { - if (localExcludes == null) { - localExcludes = new HashSet(); - if (!copyErrors) { - localExcludes.add(ACTION_ERRORS); - } - if (!copyMessages) { - localExcludes.add(ACTION_MESSAGES); - } - if (!copyFieldErrors) { - localExcludes.add(FIELD_ERRORS); - } - } - } - return localExcludes; - } - - private boolean shouldCopy(Object o) { - return o != null && !(o instanceof Unchainable); - } - - @SuppressWarnings("unchecked") - private List prepareList(CompoundRoot root) { - List list = new ArrayList(root); - list.remove(0); - Collections.reverse(list); - return list; - } - - private boolean shouldCopyStack(ActionInvocation invocation, CompoundRoot root) throws Exception { - Result result = invocation.getResult(); - return root.size() > 1 && (result == null || ActionChainResult.class.isAssignableFrom(result.getClass())); - } - - /** - * Gets list of parameter names to exclude - * - * @return the exclude list - */ - public Collection getExcludes() { - return excludes; - } - - /** - * Sets the list of parameter names to exclude from copying (all others will be included). - * - * @param excludes the excludes list as comma separated String - */ - public void setExcludes(String excludes) { - this.excludes = TextParseUtil.commaDelimitedStringToSet(excludes); - } - - /** - * Sets the list of parameter names to exclude from copying (all others will be included). - * - * @param excludes the excludes list - */ - public void setExcludesCollection(Collection excludes) { - this.excludes = excludes; - } - - /** - * Gets list of parameter names to include - * - * @return the include list - */ - public Collection getIncludes() { - return includes; - } - - /** - * Sets the list of parameter names to include when copying (all others will be excluded). - * - * @param includes the includes list as comma separated String - */ - public void setIncludes(String includes) { - this.includes = TextParseUtil.commaDelimitedStringToSet(includes); - } - - - /** - * Sets the list of parameter names to include when copying (all others will be excluded). - * - * @param includes the includes list - */ - public void setIncludesCollection(Collection includes) { - this.includes = includes; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java deleted file mode 100644 index 67fc1ada5f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ConversionErrorInterceptor.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.conversion.impl.XWorkConverter; -import com.opensymphony.xwork2.util.ValueStack; -import org.apache.commons.lang3.StringEscapeUtils; - -import java.util.HashMap; -import java.util.Map; - - -/** - * - * ConversionErrorInterceptor adds conversion errors from the ActionContext to the Action's field errors. - * - *

    - * This interceptor adds any error found in the {@link ActionContext}'s conversionErrors map as a field error (provided - * that the action implements {@link ValidationAware}). In addition, any field that contains a validation error has its - * original value saved such that any subsequent requests for that value return the original value rather than the value - * in the action. This is important because if the value "abc" is submitted and can't be converted to an int, we want to - * display the original string ("abc") again rather than the int value (likely 0, which would make very little sense to - * the user). - *

    - * - *

    - * Note: Since 2.5.2, this interceptor extends {@link MethodFilterInterceptor}, therefore being - * able to deal with excludeMethods / includeMethods parameters. See [Workflow Interceptor] - * (class {@link DefaultWorkflowInterceptor}) for documentation and examples on how to use this feature. - *

    - * - * - * - *

    Interceptor parameters:

    - * - * - * - *
      - *
    • None
    • - *
    - * - * - * - *

    Extending the interceptor:

    - * - * - * - * Because this interceptor is not web-specific, it abstracts the logic for whether an error should be added. This - * allows for web-specific interceptors to use more complex logic in the {@link #shouldAddError} method for when a value - * has a conversion error but is null or empty or otherwise indicates that the value was never actually entered by the - * user. - * - * - * - *

    Example code:

    - * - *
    - * 
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <interceptor-ref name="params"/>
    - *     <interceptor-ref name="conversionError"/>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - * 
    - * 
    - * - * @author Jason Carreira - */ -public class ConversionErrorInterceptor extends MethodFilterInterceptor { - - public static final String ORIGINAL_PROPERTY_OVERRIDE = "original.property.override"; - - protected Object getOverrideExpr(ActionInvocation invocation, Object value) { - return escape(value); - } - - protected String escape(Object value) { - return "\"" + StringEscapeUtils.escapeJava(String.valueOf(value)) + "\""; - } - - @Override - public String doIntercept(ActionInvocation invocation) throws Exception { - - ActionContext invocationContext = invocation.getInvocationContext(); - Map conversionErrors = invocationContext.getConversionErrors(); - ValueStack stack = invocationContext.getValueStack(); - - HashMap fakie = null; - - for (Map.Entry entry : conversionErrors.entrySet()) { - String propertyName = entry.getKey(); - Object value = entry.getValue(); - - if (shouldAddError(propertyName, value)) { - String message = XWorkConverter.getConversionErrorMessage(propertyName, stack); - - Object action = invocation.getAction(); - if (action instanceof ValidationAware) { - ValidationAware va = (ValidationAware) action; - va.addFieldError(propertyName, message); - } - - if (fakie == null) { - fakie = new HashMap<>(); - } - - fakie.put(propertyName, getOverrideExpr(invocation, value)); - } - } - - if (fakie != null) { - // if there were some errors, put the original (fake) values in place right before the result - stack.getContext().put(ORIGINAL_PROPERTY_OVERRIDE, fakie); - invocation.addPreResultListener(new PreResultListener() { - public void beforeResult(ActionInvocation invocation, String resultCode) { - Map fakie = (Map) invocation.getInvocationContext().get(ORIGINAL_PROPERTY_OVERRIDE); - - if (fakie != null) { - invocation.getStack().setExprOverrides(fakie); - } - } - }); - } - return invocation.invoke(); - } - - protected boolean shouldAddError(String propertyName, Object value) { - return true; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionHolder.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionHolder.java deleted file mode 100644 index 6959357f46..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionHolder.java +++ /dev/null @@ -1,77 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import java.io.IOException; -import java.io.PrintWriter; -import java.io.StringWriter; -import java.io.Serializable; - -/** - * - * - * A simple wrapper around an exception, providing an easy way to print out the stack trace of the exception as well as - * a way to get a handle on the exception itself. - * - * - * - * @author Matthew E. Porter (matthew dot porter at metissian dot com) - */ -public class ExceptionHolder implements Serializable { - - private static final long serialVersionUID = 1L; - private Exception exception; - - /** - * Holds the given exception - * - * @param exception the exception to hold. - */ - public ExceptionHolder(Exception exception) { - this.exception = exception; - } - - /** - * Gets the held exception - * - * @return the held exception - */ - public Exception getException() { - return this.exception; - } - - /** - * Gets the held exception stack trace using {@link Exception#printStackTrace()}. - * - * @return stack trace - */ - public String getExceptionStack() { - String exceptionStack = null; - - if (getException() != null) { - try (StringWriter sw = new StringWriter(); - PrintWriter pw = new PrintWriter(sw)) { - getException().printStackTrace(pw); - exceptionStack = sw.toString(); - } catch (IOException e) { - // Ignore exception generating stack trace. - } - } - - return exceptionStack; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java deleted file mode 100644 index 259fa46254..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ExceptionMappingInterceptor.java +++ /dev/null @@ -1,320 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; -import org.apache.struts2.dispatcher.HttpParameters; - -import java.util.List; -import java.util.Map; - -/** - * - *

    - * This interceptor forms the core functionality of the exception handling feature. Exception handling allows you to map - * an exception to a result code, just as if the action returned a result code instead of throwing an unexpected - * exception. When an exception is encountered, it is wrapped with an {@link ExceptionHolder} and pushed on the stack, - * providing easy access to the exception from within your result. - *

    - * - *

    - * Note: While you can configure exception mapping in your configuration file at any point, the configuration - * will not have any effect if this interceptor is not in the interceptor stack for your actions. It is recommended that - * you make this interceptor the first interceptor on the stack, ensuring that it has full access to catch any - * exception, even those caused by other interceptors. - *

    - * - * - * - *

    Interceptor parameters:

    - * - * - * - *
      - * - *
    • logEnabled (optional) - Should exceptions also be logged? (boolean true|false)
    • - * - *
    • logLevel (optional) - what log level should we use (trace, debug, info, warn, error, fatal)? - defaut is debug
    • - * - *
    • logCategory (optional) - If provided we would use this category (eg. com.mycompany.app). - * Default is to use com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.
    • - * - *
    - * - *

    - * The parameters above enables us to log all thrown exceptions with stacktace in our own logfile, - * and present a friendly webpage (with no stacktrace) to the end user. - *

    - * - * - * - *

    Extending the interceptor:

    - * - * - *

    - * If you want to add custom handling for publishing the Exception, you may override - * {@link #publishException(com.opensymphony.xwork2.ActionInvocation, ExceptionHolder)}. The default implementation - * pushes the given ExceptionHolder on value stack. A custom implementation could add additional logging etc. - *

    - * - * - *

    Example code:

    - * - *
    - * 
    - * <xwork>
    - *     <package name="default" extends="xwork-default">
    - *         <global-results>
    - *             <result name="error" type="freemarker">error.ftl</result>
    - *         </global-results>
    - *
    - *         <global-exception-mappings>
    - *             <exception-mapping exception="java.lang.Exception" result="error"/>
    - *         </global-exception-mappings>
    - *
    - *         <action name="test">
    - *             <interceptor-ref name="exception"/>
    - *             <interceptor-ref name="basicStack"/>
    - *             <exception-mapping exception="com.acme.CustomException" result="custom_error"/>
    - *             <result name="custom_error">custom_error.ftl</result>
    - *             <result name="success" type="freemarker">test.ftl</result>
    - *         </action>
    - *     </package>
    - * </xwork>
    - * 
    - * 
    - * - *

    - * This second example will also log the exceptions using our own category - * com.mycompany.app.unhandled at WARN level. - *

    - * - *
    - * 
    - * <xwork>
    - *   <package name="something" extends="xwork-default">
    - *      <interceptors>
    - *          <interceptor-stack name="exceptionmappingStack">
    - *              <interceptor-ref name="exception">
    - *                  <param name="logEnabled">true</param>
    - *                  <param name="logCategory">com.mycompany.app.unhandled</param>
    - *                  <param name="logLevel">WARN</param>	        		
    - *              </interceptor-ref>	
    - *              <interceptor-ref name="i18n"/>
    - *              <interceptor-ref name="staticParams"/>
    - *              <interceptor-ref name="params"/>
    - *              <interceptor-ref name="validation">
    - *                  <param name="excludeMethods">input,back,cancel,browse</param>
    - *              </interceptor-ref>
    - *          </interceptor-stack>
    - *      </interceptors>
    - *
    - *      <default-interceptor-ref name="exceptionmappingStack"/>
    - *    
    - *      <global-results>
    - *           <result name="unhandledException">/unhandled-exception.jsp</result>
    - *      </global-results>
    - *
    - *      <global-exception-mappings>
    - *           <exception-mapping exception="java.lang.Exception" result="unhandledException"/>
    - *      </global-exception-mappings>
    - *        
    - *      <action name="exceptionDemo" class="org.apache.struts2.showcase.exceptionmapping.ExceptionMappingAction">
    - *          <exception-mapping exception="org.apache.struts2.showcase.exceptionmapping.ExceptionMappingException"
    - *                             result="damm"/>
    - *          <result name="input">index.jsp</result>
    - *          <result name="success">success.jsp</result>            
    - *          <result name="damm">damm.jsp</result>
    - *      </action>
    - *
    - *   </package>
    - * </xwork>
    - * 
    - * 
    - * - * @author Matthew E. Porter (matthew dot porter at metissian dot com) - * @author Claus Ibsen - */ -public class ExceptionMappingInterceptor extends AbstractInterceptor { - - private static final Logger LOG = LogManager.getLogger(ExceptionMappingInterceptor.class); - - protected Logger categoryLogger; - protected boolean logEnabled = false; - protected String logCategory; - protected String logLevel; - - - public boolean isLogEnabled() { - return logEnabled; - } - - public void setLogEnabled(boolean logEnabled) { - this.logEnabled = logEnabled; - } - - public String getLogCategory() { - return logCategory; - } - - public void setLogCategory(String logCatgory) { - this.logCategory = logCatgory; - } - - public String getLogLevel() { - return logLevel; - } - - public void setLogLevel(String logLevel) { - this.logLevel = logLevel; - } - - @Override - public String intercept(ActionInvocation invocation) throws Exception { - String result; - - try { - result = invocation.invoke(); - } catch (Exception e) { - if (isLogEnabled()) { - handleLogging(e); - } - List exceptionMappings = invocation.getProxy().getConfig().getExceptionMappings(); - ExceptionMappingConfig mappingConfig = this.findMappingFromExceptions(exceptionMappings, e); - if (mappingConfig != null && mappingConfig.getResult()!=null) { - Map mappingParams = mappingConfig.getParams(); - // create a mutable HashMap since some interceptors will remove parameters, and parameterMap is immutable - HttpParameters parameters = HttpParameters.create(mappingParams).build(); - invocation.getInvocationContext().setParameters(parameters); - result = mappingConfig.getResult(); - publishException(invocation, new ExceptionHolder(e)); - } else { - throw e; - } - } - - return result; - } - - /** - * Handles the logging of the exception. - * - * @param e the exception to log. - */ - protected void handleLogging(Exception e) { - if (logCategory != null) { - if (categoryLogger == null) { - // init category logger - categoryLogger = LogManager.getLogger(logCategory); - } - doLog(categoryLogger, e); - } else { - doLog(LOG, e); - } - } - - /** - * Performs the actual logging. - * - * @param logger the provided logger to use. - * @param e the exception to log. - */ - protected void doLog(Logger logger, Exception e) { - if (logLevel == null) { - logger.debug(e.getMessage(), e); - return; - } - - if ("trace".equalsIgnoreCase(logLevel)) { - logger.trace(e.getMessage(), e); - } else if ("debug".equalsIgnoreCase(logLevel)) { - logger.debug(e.getMessage(), e); - } else if ("info".equalsIgnoreCase(logLevel)) { - logger.info(e.getMessage(), e); - } else if ("warn".equalsIgnoreCase(logLevel)) { - logger.warn(e.getMessage(), e); - } else if ("error".equalsIgnoreCase(logLevel)) { - logger.error(e.getMessage(), e); - } else if ("fatal".equalsIgnoreCase(logLevel)) { - logger.fatal(e.getMessage(), e); - } else { - throw new IllegalArgumentException("LogLevel [" + logLevel + "] is not supported"); - } - } - - /** - * Try to find appropriate {@link ExceptionMappingConfig} based on provided Throwable - * - * @param exceptionMappings list of defined exception mappings - * @param t caught exception - * @return appropriate mapping or null - */ - protected ExceptionMappingConfig findMappingFromExceptions(List exceptionMappings, Throwable t) { - ExceptionMappingConfig config = null; - // Check for specific exception mappings. - if (exceptionMappings != null) { - int deepest = Integer.MAX_VALUE; - for (Object exceptionMapping : exceptionMappings) { - ExceptionMappingConfig exceptionMappingConfig = (ExceptionMappingConfig) exceptionMapping; - int depth = getDepth(exceptionMappingConfig.getExceptionClassName(), t); - if (depth >= 0 && depth < deepest) { - deepest = depth; - config = exceptionMappingConfig; - } - } - } - return config; - } - - /** - * Return the depth to the superclass matching. 0 means ex matches exactly. Returns -1 if there's no match. - * Otherwise, returns depth. Lowest depth wins. - * - * @param exceptionMapping the mapping classname - * @param t the cause - * @return the depth, if not found -1 is returned. - */ - public int getDepth(String exceptionMapping, Throwable t) { - return getDepth(exceptionMapping, t.getClass(), 0); - } - - private int getDepth(String exceptionMapping, Class exceptionClass, int depth) { - if (exceptionClass.getName().contains(exceptionMapping)) { - // Found it! - return depth; - } - // If we've gone as far as we can go and haven't found it... - if (exceptionClass.equals(Throwable.class)) { - return -1; - } - return getDepth(exceptionMapping, exceptionClass.getSuperclass(), depth + 1); - } - - /** - * Default implementation to handle ExceptionHolder publishing. Pushes given ExceptionHolder on the stack. - * Subclasses may override this to customize publishing. - * - * @param invocation The invocation to publish Exception for. - * @param exceptionHolder The exceptionHolder wrapping the Exception to publish. - */ - protected void publishException(ActionInvocation invocation, ExceptionHolder exceptionHolder) { - invocation.getStack().push(exceptionHolder); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/LoggingInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/LoggingInterceptor.java deleted file mode 100644 index c6d913188d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/LoggingInterceptor.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionInvocation; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - - -/** - * - *

    - * This interceptor logs the start and end of the execution an action (in English-only, not internationalized). - *
    - * Note:: This interceptor will log at INFO level. - *

    - * - * - * - * There are no parameters for this interceptor. - * - * - * - * There are no obvious extensions to the existing interceptor. - * - * - *
    - * 
    - * <!-- prints out a message before and after the immediate action execution -->
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <interceptor-ref name="completeStack"/>
    - *     <interceptor-ref name="logger"/>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - *
    - * <!-- prints out a message before any more interceptors continue and after they have finished -->
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <interceptor-ref name="logger"/>
    - *     <interceptor-ref name="completeStack"/>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - * 
    - * 
    - * - * @author Jason Carreira - */ -public class LoggingInterceptor extends AbstractInterceptor { - private static final Logger LOG = LogManager.getLogger(LoggingInterceptor.class); - private static final String FINISH_MESSAGE = "Finishing execution stack for action "; - private static final String START_MESSAGE = "Starting execution stack for action "; - - @Override - public String intercept(ActionInvocation invocation) throws Exception { - logMessage(invocation, START_MESSAGE); - String result = invocation.invoke(); - logMessage(invocation, FINISH_MESSAGE); - return result; - } - - private void logMessage(ActionInvocation invocation, String baseMessage) { - if (LOG.isInfoEnabled()) { - StringBuilder message = new StringBuilder(baseMessage); - String namespace = invocation.getProxy().getNamespace(); - - if ((namespace != null) && (namespace.trim().length() > 0)) { - message.append(namespace).append("/"); - } - - message.append(invocation.getProxy().getActionName()); - LOG.info(message.toString()); - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptor.java deleted file mode 100644 index 2fec0421d1..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptor.java +++ /dev/null @@ -1,122 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.util.TextParseUtil; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.Collections; -import java.util.Set; - - -/** - * - * - *

    - * MethodFilterInterceptor is an abstract Interceptor used as - * a base class for interceptors that will filter execution based on method - * names according to specified included/excluded method lists. - * - *

    - * - * Settable parameters are as follows: - * - *
      - *
    • excludeMethods - method names to be excluded from interceptor processing
    • - *
    • includeMethods - method names to be included in interceptor processing
    • - *
    - * - *

    - * - * NOTE: If method name are available in both includeMethods and - * excludeMethods, it will be considered as an included method: - * includeMethods takes precedence over excludeMethods. - * - *

    - * - * Interceptors that extends this capability include: - * - *
      - *
    • TokenInterceptor
    • - *
    • TokenSessionStoreInterceptor
    • - *
    • DefaultWorkflowInterceptor
    • - *
    • ValidationInterceptor
    • - *
    - * - * - * - * @author Alexandru Popescu - * @author Rainer Hermanns - * - * @see org.apache.struts2.interceptor.TokenInterceptor - * @see org.apache.struts2.interceptor.TokenSessionStoreInterceptor - * @see com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor - * @see com.opensymphony.xwork2.validator.ValidationInterceptor - */ -public abstract class MethodFilterInterceptor extends AbstractInterceptor { - - private static final Logger LOG = LogManager.getLogger(MethodFilterInterceptor.class); - - protected Set excludeMethods = Collections.emptySet(); - protected Set includeMethods = Collections.emptySet(); - - public void setExcludeMethods(String excludeMethods) { - this.excludeMethods = TextParseUtil.commaDelimitedStringToSet(excludeMethods); - } - - public Set getExcludeMethodsSet() { - return excludeMethods; - } - - public void setIncludeMethods(String includeMethods) { - this.includeMethods = TextParseUtil.commaDelimitedStringToSet(includeMethods); - } - - public Set getIncludeMethodsSet() { - return includeMethods; - } - - @Override - public String intercept(ActionInvocation invocation) throws Exception { - if (applyInterceptor(invocation)) { - return doIntercept(invocation); - } - return invocation.invoke(); - } - - protected boolean applyInterceptor(ActionInvocation invocation) { - String method = invocation.getProxy().getMethod(); - // ValidationInterceptor - boolean applyMethod = MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, method); - if (!applyMethod) { - LOG.debug("Skipping Interceptor... Method [{}] found in exclude list.", method); - } - return applyMethod; - } - - /** - * Subclasses must override to implement the interceptor logic. - * - * @param invocation the action invocation - * @return the result of invocation - * @throws Exception in case of any errors - */ - protected abstract String doIntercept(ActionInvocation invocation) throws Exception; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptorUtil.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptorUtil.java deleted file mode 100644 index 987d782f39..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/MethodFilterInterceptorUtil.java +++ /dev/null @@ -1,145 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.util.TextParseUtil; -import com.opensymphony.xwork2.util.WildcardHelper; - -import java.util.HashMap; -import java.util.Set; - -/** - * Utility class contains common methods used by - * {@link com.opensymphony.xwork2.interceptor.MethodFilterInterceptor}. - * - * @author tm_jee - */ -public class MethodFilterInterceptorUtil { - - /** - * Static method to decide if the specified method should be - * apply (not filtered) depending on the set of excludeMethods and - * includeMethods. - * - *
      - *
    • - * includeMethods takes precedence over excludeMethods - *
    • - *
    - * Note: Supports wildcard listings in includeMethods/excludeMethods - * - * @param excludeMethods list of methods to exclude. - * @param includeMethods list of methods to include. - * @param method the specified method to check - * @return true if the method should be applied. - */ - public static boolean applyMethod(Set excludeMethods, Set includeMethods, String method) { - - // quick check to see if any actual pattern matching is needed - boolean needsPatternMatch = false; - for (String includeMethod : includeMethods) { - if (!"*".equals(includeMethod) && includeMethod.contains("*")) { - needsPatternMatch = true; - break; - } - } - - for (String excludeMethod : excludeMethods) { - if (!"*".equals(excludeMethod) && excludeMethod.contains("*")) { - needsPatternMatch = true; - break; - } - } - - // this section will try to honor the original logic, while - // still allowing for wildcards later - if (!needsPatternMatch && (includeMethods.contains("*") || includeMethods.size() == 0) ) { - if (excludeMethods != null - && excludeMethods.contains(method) - && !includeMethods.contains(method) ) { - return false; - } - } - - // test the methods using pattern matching - WildcardHelper wildcard = new WildcardHelper(); - String methodCopy ; - if (method == null ) { // no method specified - methodCopy = ""; - } - else { - methodCopy = new String(method); - } - for (String pattern : includeMethods) { - if (pattern.contains("*")) { - int[] compiledPattern = wildcard.compilePattern(pattern); - HashMap matchedPatterns = new HashMap<>(); - boolean matches = wildcard.match(matchedPatterns, methodCopy, compiledPattern); - if (matches) { - return true; // run it, includeMethods takes precedence - } - } - else { - if (pattern.equals(methodCopy)) { - return true; // run it, includeMethods takes precedence - } - } - } - if (excludeMethods.contains("*") ) { - return false; - } - - // CHECK ME: Previous implementation used include method - for ( String pattern : excludeMethods) { - if (pattern.contains("*")) { - int[] compiledPattern = wildcard.compilePattern(pattern); - HashMap matchedPatterns = new HashMap<>(); - boolean matches = wildcard.match(matchedPatterns, methodCopy, compiledPattern); - if (matches) { - // if found, and wasn't included earlier, don't run it - return false; - } - } - else { - if (pattern.equals(methodCopy)) { - // if found, and wasn't included earlier, don't run it - return false; - } - } - } - - - // default fall-back from before changes - return includeMethods.size() == 0 || includeMethods.contains(method) || includeMethods.contains("*"); - } - - /** - * Same as {@link #applyMethod(Set, Set, String)}, except that excludeMethods - * and includeMethods are supplied as comma separated string. - * - * @param excludeMethods comma seperated string of methods to exclude. - * @param includeMethods comma seperated string of methods to include. - * @param method the specified method to check - * @return true if the method should be applied. - */ - public static boolean applyMethod(String excludeMethods, String includeMethods, String method) { - Set includeMethodsSet = TextParseUtil.commaDelimitedStringToSet(includeMethods == null? "" : includeMethods); - Set excludeMethodsSet = TextParseUtil.commaDelimitedStringToSet(excludeMethods == null? "" : excludeMethods); - - return applyMethod(excludeMethodsSet, includeMethodsSet, method); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptor.java deleted file mode 100644 index afc6edcb7b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ModelDrivenInterceptor.java +++ /dev/null @@ -1,143 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.ModelDriven; -import com.opensymphony.xwork2.util.CompoundRoot; -import com.opensymphony.xwork2.util.ValueStack; - - -/** - * - * - * Watches for {@link ModelDriven} actions and adds the action's model on to the value stack. - * - *

    Note: The ModelDrivenInterceptor must come before the both {@link StaticParametersInterceptor} and - * {@link ParametersInterceptor} if you want the parameters to be applied to the model. - *

    - *

    Note: The ModelDrivenInterceptor will only push the model into the stack when the - * model is not null, else it will be ignored. - *

    - * - * - * - *

    Interceptor parameters:

    - * - * - * - *
      - * - *
    • refreshModelBeforeResult - set to true if you want the model to be refreshed on the value stack after action - * execution and before result execution. The setting is useful if you want to change the model instance during the - * action execution phase, like when loading it from the data layer. This will result in getModel() being called at - * least twice.
    • - * - *
    - * - * - * - *

    Extending the interceptor:

    - * - * - * - * There are no known extension points to this interceptor. - * - * - * - *

    Example code:

    - * - *
    - * 
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <interceptor-ref name="modelDriven"/>
    - *     <interceptor-ref name="basicStack"/>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - * 
    - * 
    - * - * @author tm_jee - * @version $Date$ $Id$ - */ -public class ModelDrivenInterceptor extends AbstractInterceptor { - - protected boolean refreshModelBeforeResult = false; - - public void setRefreshModelBeforeResult(boolean val) { - this.refreshModelBeforeResult = val; - } - - @Override - public String intercept(ActionInvocation invocation) throws Exception { - Object action = invocation.getAction(); - - if (action instanceof ModelDriven) { - ModelDriven modelDriven = (ModelDriven) action; - ValueStack stack = invocation.getStack(); - Object model = modelDriven.getModel(); - if (model != null) { - stack.push(model); - } - if (refreshModelBeforeResult) { - invocation.addPreResultListener(new RefreshModelBeforeResult(modelDriven, model)); - } - } - return invocation.invoke(); - } - - /** - * Refreshes the model instance on the value stack, if it has changed - */ - protected static class RefreshModelBeforeResult implements PreResultListener { - private Object originalModel = null; - protected ModelDriven action; - - - public RefreshModelBeforeResult(ModelDriven action, Object model) { - this.originalModel = model; - this.action = action; - } - - public void beforeResult(ActionInvocation invocation, String resultCode) { - ValueStack stack = invocation.getStack(); - CompoundRoot root = stack.getRoot(); - - boolean needsRefresh = true; - Object newModel = action.getModel(); - - // Check to see if the new model instance is already on the stack - for (Object item : root) { - if (item.equals(newModel)) { - needsRefresh = false; - break; - } - } - - // Add the new model on the stack - if (needsRefresh) { - - // Clear off the old model instance - if (originalModel != null) { - root.remove(originalModel); - } - if (newModel != null) { - stack.push(newModel); - } - } - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/NoParameters.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/NoParameters.java deleted file mode 100644 index 2de46b1909..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/NoParameters.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - - -/** - * Marker interface to indicate no auto setting of parameters. - * - *

    - * This marker interface should be implemented by actions that do not want any - * request parameters set on them automatically (by the ParametersInterceptor). - * This may be useful if one is using the action tag and want to supply - * the parameters to the action manually using the param tag. - * It may also be useful if one for security reasons wants to make sure that - * parameters cannot be set by malicious users. - *

    - * - * @author Dick Zetterberg (dick@transitor.se) - */ -public interface NoParameters { -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptor.java deleted file mode 100644 index cb4cd1afcf..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterFilterInterceptor.java +++ /dev/null @@ -1,234 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.util.TextParseUtil; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.struts2.dispatcher.HttpParameters; - -import java.util.Collection; -import java.util.HashSet; -import java.util.Map; -import java.util.TreeMap; - -/** - * - * - * The Parameter Filter Interceptor blocks parameters from getting - * to the rest of the stack or your action. You can use multiple - * parameter filter interceptors for a given action, so, for example, - * you could use one in your default stack that filtered parameters - * you wanted blocked from every action and those you wanted blocked - * from an individual action you could add an additional interceptor - * for each action. - * - * - * - * - * - *
      - *
    • allowed - a comma delimited list of parameter prefixes - * that are allowed to pass to the action
    • - *
    • blocked - a comma delimited list of parameter prefixes - * that are not allowed to pass to the action
    • - *
    • defaultBlock - boolean (default to false) whether by - * default a given parameter is blocked. If true, then a parameter - * must have a prefix in the allowed list in order to be able - * to pass to the action - *
    - * - *

    The way parameters are filtered for the least configuration is that - * if a string is in the allowed or blocked lists, then any parameter - * that is a member of the object represented by the parameter is allowed - * or blocked respectively.

    - * - *

    For example, if the parameters are: - *

      - *
    • blocked: person,person.address.createDate,personDao
    • - *
    • allowed: person.address
    • - *
    • defaultBlock: false
    • - *
    - * - *

    - * The parameters person.name, person.phoneNum etc would be blocked - * because 'person' is in the blocked list. However, person.address.street - * and person.address.city would be allowed because person.address is - * in the allowed list (the longer string determines permissions).

    - * - * - * - * There are no known extension points to this interceptor. - * - * - *
    - * 
    - * <interceptors>
    - *   ...
    - *   <interceptor name="parameterFilter" class="com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor"/>
    - *   ...
    - * </interceptors>
    - * 
    - * <action ....>
    - *   ...
    - *   <interceptor-ref name="parameterFilter">
    - *     <param name="blocked">person,person.address.createDate,personDao</param>
    - *   </interceptor-ref>
    - *   ...
    - * </action>
    - * 
    - * 
    - * - * @author Gabe - */ -public class ParameterFilterInterceptor extends AbstractInterceptor { - - private static final Logger LOG = LogManager.getLogger(ParameterFilterInterceptor.class); - - private Collection allowed; - private Collection blocked; - private Map includesExcludesMap; - private boolean defaultBlock = false; - - @Override - public String intercept(ActionInvocation invocation) throws Exception { - - HttpParameters parameters = invocation.getInvocationContext().getParameters(); - - Map includesExcludesMap = getIncludesExcludesMap(); - - for (String param : parameters.keySet()) { - boolean currentAllowed = !isDefaultBlock(); - - for (String currRule : includesExcludesMap.keySet()) { - if (param.startsWith(currRule) && - (param.length() == currRule.length() || isPropertySeparator(param.charAt(currRule.length()))) - ) { - currentAllowed = includesExcludesMap.get(currRule); - } - } - if (!currentAllowed) { - LOG.debug("Removing param: {}", param); - parameters = parameters.remove(param); - } - } - - invocation.getInvocationContext().setParameters(parameters); - - return invocation.invoke(); - } - - /** - * Tests if the given char is a property separator char .([. - * - * @param c the char - * @return true, if char is property separator, false otherwise. - */ - private boolean isPropertySeparator(char c) { - return c == '.' || c == '(' || c == '['; - } - - private Map getIncludesExcludesMap() { - if (this.includesExcludesMap == null) { - this.includesExcludesMap = new TreeMap<>(); - - if (getAllowedCollection() != null) { - for (String e : getAllowedCollection()) { - this.includesExcludesMap.put(e, Boolean.TRUE); - } - } - if (getBlockedCollection() != null) { - for (String b : getBlockedCollection()) { - this.includesExcludesMap.put(b, Boolean.FALSE); - } - } - } - - return this.includesExcludesMap; - } - - /** - * @return Returns the defaultBlock. - */ - public boolean isDefaultBlock() { - return defaultBlock; - } - - /** - * @param defaultExclude The defaultExclude to set. - */ - public void setDefaultBlock(boolean defaultExclude) { - this.defaultBlock = defaultExclude; - } - - /** - * @return Returns the blocked. - */ - public Collection getBlockedCollection() { - return blocked; - } - - /** - * @param blocked The blocked to set. - */ - public void setBlockedCollection(Collection blocked) { - this.blocked = blocked; - } - - /** - * @param blocked The blocked paramters as comma separated String. - */ - public void setBlocked(String blocked) { - setBlockedCollection(asCollection(blocked)); - } - - /** - * @return Returns the allowed. - */ - public Collection getAllowedCollection() { - return allowed; - } - - /** - * @param allowed The allowed to set. - */ - public void setAllowedCollection(Collection allowed) { - this.allowed = allowed; - } - - /** - * @param allowed The allowed paramters as comma separated String. - */ - public void setAllowed(String allowed) { - setAllowedCollection(asCollection(allowed)); - } - - /** - * Return a collection from the comma delimited String. - * - * @param commaDelim the comma delimited String. - * @return A collection from the comma delimited String. Returns null if the string is empty. - */ - private Collection asCollection(String commaDelim) { - if (StringUtils.isBlank(commaDelim)) { - return null; - } - return TextParseUtil.commaDelimitedStringToSet(commaDelim); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterNameAware.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterNameAware.java deleted file mode 100644 index 78f53f1a1e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterNameAware.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -/** - * This interface is implemented by actions that want to declare acceptable parameters. Works in conjunction with {@link - * ParametersInterceptor}. For example, actions may want to create a white list of parameters they will accept or a - * blacklist of parameters they will reject to prevent clients from setting other unexpected (and possibly dangerous) - * parameters. - */ -public interface ParameterNameAware { - - /** - * Tests if the the action will accept the parameter with the given name. - * - * @param parameterName the parameter name - * @return true if accepted, false otherwise - */ - boolean acceptableParameterName(String parameterName); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java deleted file mode 100644 index 6155c61f1d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParameterRemoverInterceptor.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.util.TextParseUtil; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.struts2.dispatcher.Parameter; -import org.apache.struts2.dispatcher.HttpParameters; - -import java.util.Collections; -import java.util.Set; - -/** - * - * This is a simple XWork interceptor that allows parameters (matching - * one of the paramNames attribute csv value) to be - * removed from the parameter map if they match a certain value - * (matching one of the paramValues attribute csv value), before they - * are set on the action. A typical usage would be to want a dropdown/select - * to map onto a boolean value on an action. The select had the options - * none, yes and no with values -1, true and false. The true and false would - * map across correctly. However the -1 would be set to false. - * This was not desired as one might needed the value on the action to stay null. - * This interceptor fixes this by preventing the parameter from ever reaching - * the action. - * - * - * - * - *
      - *
    • paramNames - A comma separated value (csv) indicating the parameter name - * whose param value should be considered that if they match any of the - * comma separated value (csv) from paramValues attribute, shall be - * removed from the parameter map such that they will not be applied - * to the action
    • - *
    • paramValues - A comma separated value (csv) indicating the parameter value that if - * matched shall have its parameter be removed from the parameter map - * such that they will not be applied to the action
    • - *
    - * - * - * - * - * No intended extension point - * - * - *
    - * 
    - *	
    - * <action name="sample" class="org.martingilday.Sample">
    - * 	<interceptor-ref name="paramRemover">
    - *   		<param name="paramNames">aParam,anotherParam</param>
    - *   		<param name="paramValues">--,-1</param>
    - * 	</interceptor-ref>
    - * 	<interceptor-ref name="defaultStack" />
    - * 	...
    - * </action>
    - *  
    - * 
    - * 
    - * - * - * @author martin.gilday - */ -public class ParameterRemoverInterceptor extends AbstractInterceptor { - - private static final Logger LOG = LogManager.getLogger(ParameterRemoverInterceptor.class); - - private static final long serialVersionUID = 1; - - private Set paramNames = Collections.emptySet(); - private Set paramValues = Collections.emptySet(); - - - /** - * Decide if the parameter should be removed from the parameter map based on - * paramNames and paramValues. - * - * @see com.opensymphony.xwork2.interceptor.AbstractInterceptor - */ - @Override - public String intercept(ActionInvocation invocation) throws Exception { - if (!(invocation.getAction() instanceof NoParameters) - && (null != this.paramNames)) { - ActionContext ac = invocation.getInvocationContext(); - HttpParameters parameters = ac.getParameters(); - - if (parameters != null) { - for (String removeName : paramNames) { - try { - Parameter parameter = parameters.get(removeName); - if (parameter.isDefined() && this.paramValues.contains(parameter.getValue())) { - parameters.remove(removeName); - } - } catch (Exception e) { - LOG.error("Failed to convert parameter to string", e); - } - } - } - } - return invocation.invoke(); - } - - /** - * Allows paramNames attribute to be set as comma-separated-values (csv). - * - * @param paramNames the paramNames to set - */ - public void setParamNames(String paramNames) { - this.paramNames = TextParseUtil.commaDelimitedStringToSet(paramNames); - } - - - /** - * Allows paramValues attribute to be set as a comma-separated-values (csv). - * - * @param paramValues the paramValues to set - */ - public void setParamValues(String paramValues) { - this.paramValues = TextParseUtil.commaDelimitedStringToSet(paramValues); - } -} - diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java deleted file mode 100644 index 5eba95d719..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ParametersInterceptor.java +++ /dev/null @@ -1,355 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.TextProvider; -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.security.AcceptedPatternsChecker; -import com.opensymphony.xwork2.security.ExcludedPatternsChecker; -import com.opensymphony.xwork2.util.*; -import com.opensymphony.xwork2.util.reflection.ReflectionContextState; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.struts2.dispatcher.Parameter; -import org.apache.struts2.dispatcher.HttpParameters; - -import java.util.Collection; -import java.util.Comparator; -import java.util.Map; -import java.util.TreeMap; - -/** - * This interceptor sets all parameters on the value stack. - */ -public class ParametersInterceptor extends MethodFilterInterceptor { - - private static final Logger LOG = LogManager.getLogger(ParametersInterceptor.class); - - protected static final int PARAM_NAME_MAX_LENGTH = 100; - - private int paramNameMaxLength = PARAM_NAME_MAX_LENGTH; - private boolean devMode = false; - - protected boolean ordered = false; - - private ValueStackFactory valueStackFactory; - private ExcludedPatternsChecker excludedPatterns; - private AcceptedPatternsChecker acceptedPatterns; - - @Inject - public void setValueStackFactory(ValueStackFactory valueStackFactory) { - this.valueStackFactory = valueStackFactory; - } - - @Inject(XWorkConstants.DEV_MODE) - public void setDevMode(String mode) { - this.devMode = BooleanUtils.toBoolean(mode); - } - - @Inject - public void setExcludedPatterns(ExcludedPatternsChecker excludedPatterns) { - this.excludedPatterns = excludedPatterns; - } - - @Inject - public void setAcceptedPatterns(AcceptedPatternsChecker acceptedPatterns) { - this.acceptedPatterns = acceptedPatterns; - } - - /** - * If the param name exceeds the configured maximum length it will not be - * accepted. - * - * @param paramNameMaxLength Maximum length of param names - */ - public void setParamNameMaxLength(int paramNameMaxLength) { - this.paramNameMaxLength = paramNameMaxLength; - } - - static private int countOGNLCharacters(String s) { - int count = 0; - for (int i = s.length() - 1; i >= 0; i--) { - char c = s.charAt(i); - if (c == '.' || c == '[') count++; - } - return count; - } - - /** - * Compares based on number of '.' and '[' characters (fewer is higher) - */ - static final Comparator rbCollator = new Comparator() { - public int compare(String s1, String s2) { - int l1 = countOGNLCharacters(s1), - l2 = countOGNLCharacters(s2); - return l1 < l2 ? -1 : (l2 < l1 ? 1 : s1.compareTo(s2)); - } - - }; - - @Override - public String doIntercept(ActionInvocation invocation) throws Exception { - Object action = invocation.getAction(); - if (!(action instanceof NoParameters)) { - ActionContext ac = invocation.getInvocationContext(); - HttpParameters parameters = retrieveParameters(ac); - - if (LOG.isDebugEnabled()) { - LOG.debug("Setting params {}", getParameterLogMap(parameters)); - } - - if (parameters != null) { - Map contextMap = ac.getContextMap(); - try { - ReflectionContextState.setCreatingNullObjects(contextMap, true); - ReflectionContextState.setDenyMethodExecution(contextMap, true); - ReflectionContextState.setReportingConversionErrors(contextMap, true); - - ValueStack stack = ac.getValueStack(); - setParameters(action, stack, parameters); - } finally { - ReflectionContextState.setCreatingNullObjects(contextMap, false); - ReflectionContextState.setDenyMethodExecution(contextMap, false); - ReflectionContextState.setReportingConversionErrors(contextMap, false); - } - } - } - return invocation.invoke(); - } - - /** - * Gets the parameter map to apply from wherever appropriate - * - * @param ac The action context - * @return The parameter map to apply - */ - protected HttpParameters retrieveParameters(ActionContext ac) { - return ac.getParameters(); - } - - - /** - * Adds the parameters into context's ParameterMap - * - * @param ac The action context - * @param newParams The parameter map to apply - *

    - * In this class this is a no-op, since the parameters were fetched from the same location. - * In subclasses both retrieveParameters() and addParametersToContext() should be overridden. - *

    - */ - protected void addParametersToContext(ActionContext ac, Map newParams) { - } - - protected void setParameters(final Object action, ValueStack stack, HttpParameters parameters) { - HttpParameters params; - Map acceptableParameters; - if (ordered) { - params = HttpParameters.create().withComparator(getOrderedComparator()).withParent(parameters).build(); - acceptableParameters = new TreeMap<>(getOrderedComparator()); - } else { - params = HttpParameters.create().withParent(parameters).build(); - acceptableParameters = new TreeMap<>(); - } - - for (String name : params.keySet()) { - Parameter parameter = params.get(name); - if (isAcceptableParameter(name, action)) { - acceptableParameters.put(name, parameter); - } - } - - ValueStack newStack = valueStackFactory.createValueStack(stack); - boolean clearableStack = newStack instanceof ClearableValueStack; - if (clearableStack) { - //if the stack's context can be cleared, do that to prevent OGNL - //from having access to objects in the stack, see XW-641 - ((ClearableValueStack)newStack).clearContextValues(); - Map context = newStack.getContext(); - ReflectionContextState.setCreatingNullObjects(context, true); - ReflectionContextState.setDenyMethodExecution(context, true); - ReflectionContextState.setReportingConversionErrors(context, true); - - //keep locale from original context - context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE)); - } - - boolean memberAccessStack = newStack instanceof MemberAccessValueStack; - if (memberAccessStack) { - //block or allow access to properties - //see WW-2761 for more details - MemberAccessValueStack accessValueStack = (MemberAccessValueStack) newStack; - accessValueStack.setAcceptProperties(acceptedPatterns.getAcceptedPatterns()); - accessValueStack.setExcludeProperties(excludedPatterns.getExcludedPatterns()); - } - - for (Map.Entry entry : acceptableParameters.entrySet()) { - String name = entry.getKey(); - Parameter value = entry.getValue(); - try { - newStack.setParameter(name, value.getObject()); - } catch (RuntimeException e) { - if (devMode) { - notifyDeveloperParameterException(action, name, e.getMessage()); - } - } - } - - if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null)) - stack.getContext().put(ActionContext.CONVERSION_ERRORS, newStack.getContext().get(ActionContext.CONVERSION_ERRORS)); - - addParametersToContext(ActionContext.getContext(), acceptableParameters); - } - - protected void notifyDeveloperParameterException(Object action, String property, String message) { - String developerNotification = "Unexpected Exception caught setting '" + property + "' on '" + action.getClass() + ": " + message; - if (action instanceof TextProvider) { - TextProvider tp = (TextProvider) action; - developerNotification = tp.getText("devmode.notification", - "Developer Notification:\n{0}", - new String[]{ developerNotification } - ); - } - - LOG.error(developerNotification); - - if (action instanceof ValidationAware) { - // see https://issues.apache.org/jira/browse/WW-4066 - Collection messages = ((ValidationAware) action).getActionMessages(); - messages.add(message); - ((ValidationAware) action).setActionMessages(messages); - } - } - - /** - * Checks if name of parameter can be accepted or thrown away - * - * @param name parameter name - * @param action current action - * @return true if parameter is accepted - */ - protected boolean isAcceptableParameter(String name, Object action) { - ParameterNameAware parameterNameAware = (action instanceof ParameterNameAware) ? (ParameterNameAware) action : null; - return acceptableName(name) && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name)); - } - - /** - * Gets an instance of the comparator to use for the ordered sorting. Override this - * method to customize the ordering of the parameters as they are set to the - * action. - * - * @return A comparator to sort the parameters - */ - protected Comparator getOrderedComparator() { - return rbCollator; - } - - protected String getParameterLogMap(HttpParameters parameters) { - if (parameters == null) { - return "NONE"; - } - - StringBuilder logEntry = new StringBuilder(); - for (String name : parameters.keySet()) { - logEntry.append(String.valueOf(name)); - logEntry.append(" => "); - logEntry.append(parameters.get(name).getValue()); - } - - return logEntry.toString(); - } - - protected boolean acceptableName(String name) { - boolean accepted = isWithinLengthLimit(name) && !isExcluded(name) && isAccepted(name); - if (devMode && accepted) { // notify only when in devMode - LOG.debug("Parameter [{}] was accepted and will be appended to action!", name); - } - return accepted; - } - - protected boolean isWithinLengthLimit( String name ) { - boolean matchLength = name.length() <= paramNameMaxLength; - if (!matchLength) { - LOG.debug("Parameter [{}] is too long, allowed length is [{}]", name, String.valueOf(paramNameMaxLength)); - } - return matchLength; - } - - protected boolean isAccepted(String paramName) { - AcceptedPatternsChecker.IsAccepted result = acceptedPatterns.isAccepted(paramName); - if (result.isAccepted()) { - return true; - } - LOG.debug("Parameter [{}] didn't match accepted pattern [{}]!", paramName, result.getAcceptedPattern()); - return false; - } - - protected boolean isExcluded(String paramName) { - ExcludedPatternsChecker.IsExcluded result = excludedPatterns.isExcluded(paramName); - if (result.isExcluded()) { - LOG.debug("Parameter [{}] matches excluded pattern [{}]!", paramName, result.getExcludedPattern()); - return true; - } - return false; - } - - /** - * Whether to order the parameters or not - * - * @return True to order - */ - public boolean isOrdered() { - return ordered; - } - - /** - * Set whether to order the parameters by object depth or not - * - * @param ordered True to order them - */ - public void setOrdered(boolean ordered) { - this.ordered = ordered; - } - - /** - * Sets a comma-delimited list of regular expressions to match - * parameters that are allowed in the parameter map (aka whitelist). - *

    - * Don't change the default unless you know what you are doing in terms - * of security implications. - *

    - * - * @param commaDelim A comma-delimited list of regular expressions - */ - public void setAcceptParamNames(String commaDelim) { - acceptedPatterns.setAcceptedPatterns(commaDelim); - } - - /** - * Sets a comma-delimited list of regular expressions to match - * parameters that should be removed from the parameter map. - * - * @param commaDelim A comma-delimited list of regular expressions - */ - public void setExcludeParams(String commaDelim) { - excludedPatterns.setExcludedPatterns(commaDelim); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/PreResultListener.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/PreResultListener.java deleted file mode 100644 index 12643a3d2f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/PreResultListener.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionInvocation; - - -/** - * PreResultListeners may be registered with an {@link ActionInvocation} to get a callback after the - * {@link com.opensymphony.xwork2.Action} has been executed but before the {@link com.opensymphony.xwork2.Result} - * is executed. - * - * @author Jason Carreira - */ -public interface PreResultListener { - - /** - * This callback method will be called after the {@link com.opensymphony.xwork2.Action} execution and - * before the {@link com.opensymphony.xwork2.Result} execution. - * - * @param invocation the action invocation - * @param resultCode the result code returned by the action (eg. success). - */ - void beforeResult(ActionInvocation invocation, String resultCode); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java deleted file mode 100644 index 70516cddc0..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/PrefixMethodInvocationUtil.java +++ /dev/null @@ -1,178 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionInvocation; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; - -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; - -/** - *

    - * A utility class for invoking prefixed methods in action class. - * - * Interceptors that made use of this class are: - *

    - *
      - *
    • DefaultWorkflowInterceptor
    • - *
    • PrepareInterceptor
    • - *
    - * * - * - * - * In DefaultWorkflowInterceptor - *

    applies only when action implements {@link com.opensymphony.xwork2.Validateable}

    - *
      - *
    1. if the action class have validate{MethodName}(), it will be invoked
    2. - *
    3. else if the action class have validateDo{MethodName}(), it will be invoked
    4. - *
    5. no matter if 1] or 2] is performed, if alwaysInvokeValidate property of the interceptor is "true" (which is by default "true"), validate() will be invoked.
    6. - *
    - * - * - * - * - * - * - * In PrepareInterceptor - *

    Applies only when action implements Preparable

    - *
      - *
    1. if the action class have prepare{MethodName}(), it will be invoked
    2. - *
    3. else if the action class have prepareDo(MethodName()}(), it will be invoked
    4. - *
    5. no matter if 1] or 2] is performed, if alwaysinvokePrepare property of the interceptor is "true" (which is by default "true"), prepare() will be invoked.
    6. - *
    - * - * - * - * @author Philip Luppens - * @author tm_jee - */ -public class PrefixMethodInvocationUtil { - - private static final Logger LOG = LogManager.getLogger(PrefixMethodInvocationUtil.class); - - private static final String DEFAULT_INVOCATION_METHODNAME = "execute"; - - private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; - - /** - *

    - * This method will prefix actionInvocation's ActionProxy's - * method with prefixes before invoking the prefixed method. - * Order of the prefixes is important, as this method will return once - * a prefixed method is found in the action class. - *

    - * - *

    - * For example, with - *

    - * - *
    -	 *   invokePrefixMethod(actionInvocation, new String[] { "prepare", "prepareDo" });
    -	 * 
    - * - *

    - * Assuming actionInvocation.getProxy(),getMethod() returns "submit", - * the order of invocation would be as follows:- - *

    - * - *
      - *
    1. prepareSubmit()
    2. - *
    3. prepareDoSubmit()
    4. - *
    - * - *

    - * If prepareSubmit() exists, it will be invoked and this method - * will return, prepareDoSubmit() will NOT be invoked. - *

    - * - *

    - * On the other hand, if prepareDoSubmit() does not exists, and - * prepareDoSubmit() exists, it will be invoked. - *

    - * - *

    - * If none of those two methods exists, nothing will be invoked. - *

    - * - * @param actionInvocation the action invocation - * @param prefixes prefixes for method names - * @throws InvocationTargetException is thrown if invocation of a method failed. - * @throws IllegalAccessException is thrown if invocation of a method failed. - */ - public static void invokePrefixMethod(ActionInvocation actionInvocation, String[] prefixes) throws InvocationTargetException, IllegalAccessException { - Object action = actionInvocation.getAction(); - - String methodName = actionInvocation.getProxy().getMethod(); - - if (methodName == null) { - // if null returns (possible according to the docs), use the default execute - methodName = DEFAULT_INVOCATION_METHODNAME; - } - - Method method = getPrefixedMethod(prefixes, methodName, action); - if (method != null) { - method.invoke(action, new Object[0]); - } - } - - - /** - * This method returns a {@link Method} in action. The method - * returned is found by searching for method in action whose method name - * is equals to the result of appending each prefixes - * to methodName. Only the first method found will be returned, hence - * the order of prefixes is important. If none is found this method - * will return null. - * - * @param prefixes the prefixes to prefix the methodName - * @param methodName the method name to be prefixed with prefixes - * @param action the action class of which the prefixed method is to be search for. - * @return a {@link Method} if one is found, else null. - */ - public static Method getPrefixedMethod(String[] prefixes, String methodName, Object action) { - assert(prefixes != null); - String capitalizedMethodName = capitalizeMethodName(methodName); - for (String prefixe : prefixes) { - String prefixedMethodName = prefixe + capitalizedMethodName; - try { - return action.getClass().getMethod(prefixedMethodName, EMPTY_CLASS_ARRAY); - } - catch (NoSuchMethodException e) { - // hmm -- OK, try next prefix - LOG.debug("Cannot find method [{}] in action [{}]", prefixedMethodName, action); - } - } - return null; - } - - /** - *

    - * This method capitalized the first character of methodName. - *
    - * eg. capitalizeMethodName("someMethod"); will return "SomeMethod". - *

    - * - * @param methodName the method name - * @return capitalized method name - */ - public static String capitalizeMethodName(String methodName) { - assert(methodName != null); - return methodName.substring(0, 1).toUpperCase() + methodName.substring(1); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ScopedModelDriven.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ScopedModelDriven.java deleted file mode 100644 index d8f84c5418..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ScopedModelDriven.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ModelDriven; - -/** - * Adds the ability to set a model, probably retrieved from a given state. - */ -public interface ScopedModelDriven extends ModelDriven { - - /** - * @param model sets the model - */ - void setModel(T model); - - /** - * Sets the key under which the model is stored - * @param key The model key - */ - void setScopeKey(String key); - - /** - * @return the key under which the model is stored - */ - String getScopeKey(); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptor.java deleted file mode 100644 index 858a33e899..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ScopedModelDrivenInterceptor.java +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.XWorkException; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.inject.Inject; - -import java.lang.reflect.Method; -import java.util.Map; - -/** - * - * - * An interceptor that enables scoped model-driven actions. - * - *

    This interceptor only activates on actions that implement the {@link ScopedModelDriven} interface. If - * detected, it will retrieve the model class from the configured scope, then provide it to the Action.

    - * - * - * - *

    Interceptor parameters:

    - * - * - * - *
      - * - *
    • className - The model class name. Defaults to the class name of the object returned by the getModel() method.
    • - * - *
    • name - The key to use when storing or retrieving the instance in a scope. Defaults to the model - * class name.
    • - * - *
    • scope - The scope to store and retrieve the model. Defaults to 'request' but can also be 'session'.
    • - *
    - * - * - * - *

    Extending the interceptor:

    - * - * - * - * There are no known extension points for this interceptor. - * - * - * - *

    Example code:

    - * - *
    - * 
    - * 
    - * <-- Basic usage -->
    - * <interceptor name="scopedModelDriven" class="com.opensymphony.interceptor.ScopedModelDrivenInterceptor" />
    - * 
    - * <-- Using all available parameters -->
    - * <interceptor name="gangsterForm" class="com.opensymphony.interceptor.ScopedModelDrivenInterceptor">
    - *      <param name="scope">session</param>
    - *      <param name="name">gangsterForm</param>
    - *      <param name="className">com.opensymphony.example.GangsterForm</param>
    - *  </interceptor>
    - * 
    - * 
    - * 
    - */ -public class ScopedModelDrivenInterceptor extends AbstractInterceptor { - - private static final Class[] EMPTY_CLASS_ARRAY = new Class[0]; - - private static final String GET_MODEL = "getModel"; - private String scope; - private String name; - private String className; - private ObjectFactory objectFactory; - - @Inject - public void setObjectFactory(ObjectFactory factory) { - this.objectFactory = factory; - } - - protected Object resolveModel(ObjectFactory factory, ActionContext actionContext, String modelClassName, String modelScope, String modelName) throws Exception { - Object model; - Map scopeMap = actionContext.getContextMap(); - if ("session".equals(modelScope)) { - scopeMap = actionContext.getSession(); - } - - model = scopeMap.get(modelName); - if (model == null) { - model = factory.buildBean(modelClassName, null); - scopeMap.put(modelName, model); - } - return model; - } - - @Override - public String intercept(ActionInvocation invocation) throws Exception { - Object action = invocation.getAction(); - - if (action instanceof ScopedModelDriven) { - ScopedModelDriven modelDriven = (ScopedModelDriven) action; - if (modelDriven.getModel() == null) { - ActionContext ctx = ActionContext.getContext(); - ActionConfig config = invocation.getProxy().getConfig(); - - String cName = className; - if (cName == null) { - try { - Method method = action.getClass().getMethod(GET_MODEL, EMPTY_CLASS_ARRAY); - Class cls = method.getReturnType(); - cName = cls.getName(); - } catch (NoSuchMethodException e) { - throw new XWorkException("The " + GET_MODEL + "() is not defined in action " + action.getClass() + "", config); - } - } - String modelName = name; - if (modelName == null) { - modelName = cName; - } - Object model = resolveModel(objectFactory, ctx, cName, scope, modelName); - modelDriven.setModel(model); - modelDriven.setScopeKey(modelName); - } - } - return invocation.invoke(); - } - - /** - * @param className the className to set - */ - public void setClassName(String className) { - this.className = className; - } - - /** - * @param name the name to set - */ - public void setName(String name) { - this.name = name; - } - - /** - * @param scope the scope to set - */ - public void setScope(String scope) { - this.scope = scope; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java deleted file mode 100644 index e4eaa4705d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/StaticParametersInterceptor.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.config.entities.Parameterizable; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ClearableValueStack; -import com.opensymphony.xwork2.LocalizedTextProvider; -import com.opensymphony.xwork2.util.TextParseUtil; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.util.ValueStackFactory; -import com.opensymphony.xwork2.util.reflection.ReflectionContextState; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.struts2.dispatcher.HttpParameters; - -import java.util.Collections; -import java.util.Map; - - -/** - * - * - * This interceptor populates the action with the static parameters defined in the action configuration. If the action - * implements {@link Parameterizable}, a map of the static parameters will be also be passed directly to the action. - * The static params will be added to the request params map, unless "merge" is set to false. - * - *

    Parameters are typically defined with <param> elements within xwork.xml.

    - * - * - * - *

    Interceptor parameters:

    - * - * - * - *
      - * - *
    • None
    • - * - *
    - * - * - * - *

    Extending the interceptor:

    - * - * - * - *

    There are no extension points to this interceptor.

    - * - * - * - *

    Example code:

    - * - *
    - * 
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <interceptor-ref name="staticParams">
    - *          <param name="parse">true</param>
    - *          <param name="overwrite">false</param>
    - *     </interceptor-ref>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - * 
    - * 
    - * - * @author Patrick Lightbody - */ -public class StaticParametersInterceptor extends AbstractInterceptor { - - private boolean parse; - private boolean overwrite; - private boolean merge = true; - private boolean devMode = false; - - private static final Logger LOG = LogManager.getLogger(StaticParametersInterceptor.class); - - private ValueStackFactory valueStackFactory; - private LocalizedTextProvider localizedTextProvider; - - @Inject - public void setValueStackFactory(ValueStackFactory valueStackFactory) { - this.valueStackFactory = valueStackFactory; - } - - @Inject(XWorkConstants.DEV_MODE) - public void setDevMode(String mode) { - devMode = BooleanUtils.toBoolean(mode); - } - - @Inject - public void setLocalizedTextProvider(LocalizedTextProvider localizedTextProvider) { - this.localizedTextProvider = localizedTextProvider; - } - - public void setParse(String value) { - this.parse = BooleanUtils.toBoolean(value); - } - - public void setMerge(String value) { - this.merge = BooleanUtils.toBoolean(value); - } - - /** - * Overwrites already existing parameters from other sources. - * Static parameters are the successor over previously set parameters, if true. - * - * @param value enable overwrites of already existing parameters from other sources - */ - public void setOverwrite(String value) { - this.overwrite = BooleanUtils.toBoolean(value); - } - - @Override - public String intercept(ActionInvocation invocation) throws Exception { - ActionConfig config = invocation.getProxy().getConfig(); - Object action = invocation.getAction(); - - final Map parameters = config.getParams(); - - LOG.debug("Setting static parameters: {}", parameters); - - // for actions marked as Parameterizable, pass the static parameters directly - if (action instanceof Parameterizable) { - ((Parameterizable) action).setParams(parameters); - } - - if (parameters != null) { - ActionContext ac = ActionContext.getContext(); - Map contextMap = ac.getContextMap(); - try { - ReflectionContextState.setCreatingNullObjects(contextMap, true); - ReflectionContextState.setReportingConversionErrors(contextMap, true); - final ValueStack stack = ac.getValueStack(); - - ValueStack newStack = valueStackFactory.createValueStack(stack); - boolean clearableStack = newStack instanceof ClearableValueStack; - if (clearableStack) { - //if the stack's context can be cleared, do that to prevent OGNL - //from having access to objects in the stack, see XW-641 - ((ClearableValueStack)newStack).clearContextValues(); - Map context = newStack.getContext(); - ReflectionContextState.setCreatingNullObjects(context, true); - ReflectionContextState.setDenyMethodExecution(context, true); - ReflectionContextState.setReportingConversionErrors(context, true); - - //keep locale from original context - context.put(ActionContext.LOCALE, stack.getContext().get(ActionContext.LOCALE)); - } - - for (Map.Entry entry : parameters.entrySet()) { - Object val = entry.getValue(); - if (parse && val instanceof String) { - val = TextParseUtil.translateVariables(val.toString(), stack); - } - try { - newStack.setValue(entry.getKey(), val); - } catch (RuntimeException e) { - if (devMode) { - - String developerNotification = localizedTextProvider.findText(ParametersInterceptor.class, "devmode.notification", ActionContext.getContext().getLocale(), "Developer Notification:\n{0}", new Object[]{ - "Unexpected Exception caught setting '" + entry.getKey() + "' on '" + action.getClass() + ": " + e.getMessage() - }); - LOG.error(developerNotification); - if (action instanceof ValidationAware) { - ((ValidationAware) action).addActionMessage(developerNotification); - } - } - } - } - - if (clearableStack && (stack.getContext() != null) && (newStack.getContext() != null)) - stack.getContext().put(ActionContext.CONVERSION_ERRORS, newStack.getContext().get(ActionContext.CONVERSION_ERRORS)); - - if (merge) - addParametersToContext(ac, parameters); - } finally { - ReflectionContextState.setCreatingNullObjects(contextMap, false); - ReflectionContextState.setReportingConversionErrors(contextMap, false); - } - } - return invocation.invoke(); - } - - - /** - * @param ac The action context - * @return the parameters from the action mapping in the context. If none found, returns - * an empty map. - */ - protected Map retrieveParameters(ActionContext ac) { - ActionConfig config = ac.getActionInvocation().getProxy().getConfig(); - if (config != null) { - return config.getParams(); - } else { - return Collections.emptyMap(); - } - } - - /** - * Adds the parameters into context's ParameterMap. - * As default, static parameters will not overwrite existing parameters from other sources. - * If you want the static parameters as successor over already existing parameters, set overwrite to true. - * - * @param ac The action context - * @param newParams The parameter map to apply - */ - protected void addParametersToContext(ActionContext ac, Map newParams) { - HttpParameters previousParams = ac.getParameters(); - - HttpParameters.Builder combinedParams = HttpParameters.create(); - if (overwrite) { - if (previousParams != null) { - combinedParams = combinedParams.withParent(previousParams); - } - if (newParams != null) { - combinedParams = combinedParams.withExtraParams(newParams); - } - } else { - if (newParams != null) { - combinedParams = combinedParams.withExtraParams(newParams); - } - if (previousParams != null) { - combinedParams = combinedParams.withParent(previousParams); - } - } - ac.setParameters(combinedParams.build()); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/TimerInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/TimerInterceptor.java deleted file mode 100644 index d2cc534720..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/TimerInterceptor.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionInvocation; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -/** - * - * This interceptor logs the amount of time in milliseconds. In order for this interceptor to work properly, the - * logging framework must be set to at least the INFO level. - * This interceptor relies on the Commons Logging API to - * report its execution-time value. - * - * - * - * - *
      - * - *
    • logLevel (optional) - what log level should we use (trace, debug, info, warn, error, fatal)? - defaut is info
    • - * - *
    • logCategory (optional) - If provided we would use this category (eg. com.mycompany.app). - * Default is to use com.opensymphony.xwork2.interceptor.TimerInterceptor.
    • - * - *
    - * - * The parameters above enables us to log all action execution times in our own logfile. - * - * - * - * - * This interceptor can be extended to provide custom message format. Users should override the - * invokeUnderTiming method. - * - * - *
    - * 
    - * <!-- records only the action's execution time -->
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <interceptor-ref name="completeStack"/>
    - *     <interceptor-ref name="timer"/>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - *
    - * <!-- records action's execution time as well as other interceptors-->
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <interceptor-ref name="timer"/>
    - *     <interceptor-ref name="completeStack"/>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - * 
    - * 
    - * - * This second example uses our own log category at debug level. - * - *
    - * 
    - * <!-- records only the action's execution time -->
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <interceptor-ref name="completeStack"/>
    - *     <interceptor-ref name="timer">
    - *         <param name="logLevel">debug</param>
    - *         <param name="logCategory">com.mycompany.myapp.actiontime</param>
    - *     <interceptor-ref/>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - *
    - * <!-- records action's execution time as well as other interceptors-->
    - * <action name="someAction" class="com.examples.SomeAction">
    - *     <interceptor-ref name="timer"/>
    - *     <interceptor-ref name="completeStack"/>
    - *     <result name="success">good_result.ftl</result>
    - * </action>
    - * 
    - * 
    - * - * @author Jason Carreira - * @author Claus Ibsen - */ -public class TimerInterceptor extends AbstractInterceptor { - - private static final Logger LOG = LogManager.getLogger(TimerInterceptor.class); - - protected Logger categoryLogger; - protected String logCategory; - protected String logLevel; - - public String getLogCategory() { - return logCategory; - } - - public void setLogCategory(String logCatgory) { - this.logCategory = logCatgory; - } - - public String getLogLevel() { - return logLevel; - } - - public void setLogLevel(String logLevel) { - this.logLevel = logLevel; - } - - @Override - public String intercept(ActionInvocation invocation) throws Exception { - if (! shouldLog()) { - return invocation.invoke(); - } else { - return invokeUnderTiming(invocation); - } - } - - /** - * Is called to invoke the action invocation and time the execution time. - * - * @param invocation the action invocation. - * @return the result of the action execution. - * @throws Exception can be thrown from the action. - */ - protected String invokeUnderTiming(ActionInvocation invocation) throws Exception { - long startTime = System.currentTimeMillis(); - String result = invocation.invoke(); - long executionTime = System.currentTimeMillis() - startTime; - - StringBuilder message = new StringBuilder(100); - message.append("Executed action ["); - String namespace = invocation.getProxy().getNamespace(); - if (StringUtils.isNotBlank(namespace)) { - message.append(namespace).append("/"); - } - message.append(invocation.getProxy().getActionName()); - message.append("!"); - message.append(invocation.getProxy().getMethod()); - message.append("] took ").append(executionTime).append(" ms."); - - doLog(getLoggerToUse(), message.toString()); - - return result; - } - - /** - * Determines if we should log the time. - * - * @return true to log, false to not log. - */ - protected boolean shouldLog() { - // default check first - if (logLevel == null && logCategory == null) { - return LOG.isInfoEnabled(); - } - - // okay user have set some parameters - return isLoggerEnabled(getLoggerToUse(), logLevel); - } - - /** - * Get's the logger to use. - * - * @return the logger to use. - */ - protected Logger getLoggerToUse() { - if (logCategory != null) { - if (categoryLogger == null) { - // init category logger - categoryLogger = LogManager.getLogger(logCategory); - if (logLevel == null) { - logLevel = "info"; // use info as default if not provided - } - } - return categoryLogger; - } - - return LOG; - } - - /** - * Performs the actual logging. - * - * @param logger the provided logger to use. - * @param message the message to log. - */ - protected void doLog(Logger logger, String message) { - if (logLevel == null) { - logger.info(message); - return; - } - - if ("debug".equalsIgnoreCase(logLevel)) { - logger.debug(message); - } else if ("info".equalsIgnoreCase(logLevel)) { - logger.info(message); - } else if ("warn".equalsIgnoreCase(logLevel)) { - logger.warn(message); - } else if ("error".equalsIgnoreCase(logLevel)) { - logger.error(message); - } else if ("fatal".equalsIgnoreCase(logLevel)) { - logger.fatal(message); - } else if ("trace".equalsIgnoreCase(logLevel)) { - logger.trace(message); - } else { - throw new IllegalArgumentException("LogLevel [" + logLevel + "] is not supported"); - } - } - - /** - * Is the given logger enalbed at the given level? - * - * @param logger the logger. - * @param level the level to check if isXXXEnabled. - * @return true if enabled, false if not. - */ - private static boolean isLoggerEnabled(Logger logger, String level) { - if ("debug".equalsIgnoreCase(level)) { - return logger.isDebugEnabled(); - } else if ("info".equalsIgnoreCase(level)) { - return logger.isInfoEnabled(); - } else if ("warn".equalsIgnoreCase(level)) { - return logger.isWarnEnabled(); - } else if ("error".equalsIgnoreCase(level)) { - return logger.isErrorEnabled(); - } else if ("fatal".equalsIgnoreCase(level)) { - return logger.isFatalEnabled(); - } else if ("trace".equalsIgnoreCase(level)) { - return logger.isTraceEnabled(); - } else { - throw new IllegalArgumentException("LogLevel [" + level + "] is not supported"); - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationErrorAware.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationErrorAware.java deleted file mode 100644 index 2e5e82ccd1..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationErrorAware.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.interceptor; - -/** - * ValidationErrorAware classes can be notified about validation errors - * before {@link com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor} will return 'inputResultName' result - * to allow change or not the result name - * - * This interface can be only applied to action which already implements {@link ValidationAware} interface! - * - * @since 2.3.15 - */ -public interface ValidationErrorAware { - - /** - * Allows to notify action about occurred action/field errors - * - * @param currentResultName current result name, action can change it or return the same - * @return new result name or passed currentResultName - */ - String actionErrorOccurred(final String currentResultName); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationWorkflowAware.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationWorkflowAware.java deleted file mode 100644 index f0ea87d14d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/ValidationWorkflowAware.java +++ /dev/null @@ -1,12 +0,0 @@ -package com.opensymphony.xwork2.interceptor; - -/** - * ValidationWorkflowAware classes can programmatically change result name when errors occurred - * - * This interface can be only applied to action which already implements {@link ValidationAware} interface! - */ -public interface ValidationWorkflowAware { - - String getInputResultName(); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/WithLazyParams.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/WithLazyParams.java deleted file mode 100644 index e54cc7337a..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/WithLazyParams.java +++ /dev/null @@ -1,63 +0,0 @@ -package com.opensymphony.xwork2.interceptor; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.ognl.OgnlUtil; -import com.opensymphony.xwork2.util.TextParseUtil; -import com.opensymphony.xwork2.util.TextParser; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; - -import java.util.Map; - -/** - * Interceptors marked with this interface won't be fully initialised during initialisation. - * Appropriated params will be injected just before usage of the interceptor. - * - * Please be aware that in such case {@link Interceptor#init()} method must be prepared for this. - * - * @since 2.5.9 - */ -public interface WithLazyParams { - - class LazyParamInjector { - - protected OgnlUtil ognlUtil; - protected TextParser textParser; - protected ReflectionProvider reflectionProvider; - - private final TextParseUtil.ParsedValueEvaluator valueEvaluator; - - public LazyParamInjector(final ValueStack valueStack) { - valueEvaluator = new TextParseUtil.ParsedValueEvaluator() { - public Object evaluate(String parsedValue) { - return valueStack.findValue(parsedValue); // no asType !!! - } - }; - } - - @Inject - public void setTextParser(TextParser textParser) { - this.textParser = textParser; - } - - @Inject - public void setReflectionProvider(ReflectionProvider reflectionProvider) { - this.reflectionProvider = reflectionProvider; - } - - @Inject - public void setOgnlUtil(OgnlUtil ognlUtil) { - this.ognlUtil = ognlUtil; - } - - public Interceptor injectParams(Interceptor interceptor, Map params, ActionContext invocationContext) { - for (Map.Entry entry : params.entrySet()) { - Object paramValue = textParser.evaluate(new char[]{ '$' }, entry.getValue(), valueEvaluator, TextParser.DEFAULT_LOOP_COUNT); - ognlUtil.setProperty(entry.getKey(), paramValue, interceptor, invocationContext.getContextMap()); - } - - return interceptor; - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/After.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/After.java deleted file mode 100644 index 13b0a7414f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/After.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * Marks a action method that needs to be called after the main action method and the result was - * executed. Return value is ignored. - * - * - *

    Annotation usage:

    - * - * - * The After annotation can be applied at method level. - * - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    priorityno10Priority order of method execution
    - * - * - *

    Example code:

    - * - *
    - * 
    - * public class SampleAction extends ActionSupport {
    - *
    - *  @After
    - *  public void isValid() throws ValidationException {
    - *    // validate model object, throw exception if failed
    - *  }
    - *
    - *  public String execute() {
    - *     // perform action
    - *     return SUCCESS;
    - *  }
    - * }
    - * 
    - * 
    - * - * @author Zsolt Szasz, zsolt at lorecraft dot com - * @author Rainer Hermanns - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface After { - int priority() default 10; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/Allowed.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/Allowed.java deleted file mode 100644 index 42633444ec..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/Allowed.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.opensymphony.xwork2.interceptor.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Declares that it is permitted for the field be mutated through - * a HttpRequest parameter. - * - * @author martin.gilday - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface Allowed { - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptor.java deleted file mode 100644 index b7c6e0e0f0..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterInterceptor.java +++ /dev/null @@ -1,95 +0,0 @@ -package com.opensymphony.xwork2.interceptor.annotations; - - -import com.opensymphony.xwork2.Action; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.interceptor.AbstractInterceptor; -import com.opensymphony.xwork2.interceptor.Interceptor; -import com.opensymphony.xwork2.interceptor.ParameterFilterInterceptor; -import com.opensymphony.xwork2.interceptor.ParametersInterceptor; -import com.opensymphony.xwork2.util.AnnotationUtils; -import org.apache.struts2.dispatcher.HttpParameters; - -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.HashSet; -import java.util.List; - -/** - * Annotation based version of {@link ParameterFilterInterceptor}. - * - *

    - * This {@link Interceptor} must be placed in the stack before the {@link ParametersInterceptor} - * When a parameter matches a field that is marked {@link Blocked} then it is removed from - * the parameter map. - *

    - *

    - * If an {@link Action} class is marked with {@link BlockByDefault} then all parameters are - * removed unless a field on the Action exists and is marked with {@link Allowed} - *

    - * - * @author martin.gilday - */ -public class AnnotationParameterFilterInterceptor extends AbstractInterceptor { - - /* (non-Javadoc) - * @see com.opensymphony.xwork2.interceptor.AbstractInterceptor#intercept(com.opensymphony.xwork2.ActionInvocation) - */ - @Override public String intercept(ActionInvocation invocation) throws Exception { - - final Object action = invocation.getAction(); - HttpParameters parameters = invocation.getInvocationContext().getParameters(); - - Object model = invocation.getStack().peek(); - if (model == action) { - model = null; - } - - boolean blockByDefault = action.getClass().isAnnotationPresent(BlockByDefault.class); - List annotatedFields = new ArrayList<>(); - - if (blockByDefault) { - AnnotationUtils.addAllFields(Allowed.class, action.getClass(), annotatedFields); - if (model != null) { - AnnotationUtils.addAllFields(Allowed.class, model.getClass(), annotatedFields); - } - - for (String paramName : parameters.keySet()) { - boolean allowed = false; - - for (Field field : annotatedFields) { - //TODO only matches exact field names. need to change to it matches start of ognl expression - //i.e take param name up to first . (period) and match against that - if (field.getName().equals(paramName)) { - allowed = true; - break; - } - } - - if (!allowed) { - parameters = parameters.remove(paramName); - } - } - } else { - AnnotationUtils.addAllFields(Blocked.class, action.getClass(), annotatedFields); - if (model != null) { - AnnotationUtils.addAllFields(Blocked.class, model.getClass(), annotatedFields); - } - - for (String paramName : parameters.keySet()) { - for (Field field : annotatedFields) { - //TODO only matches exact field names. need to change to it matches start of ognl expression - //i.e take param name up to first . (period) and match against that - if (field.getName().equals(paramName)) { - parameters = parameters.remove(paramName); - } - } - } - } - - invocation.getInvocationContext().setParameters(parameters); - - return invocation.invoke(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationWorkflowInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationWorkflowInterceptor.java deleted file mode 100644 index dbe4315ae0..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationWorkflowInterceptor.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor.annotations; - -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.XWorkException; -import com.opensymphony.xwork2.interceptor.AbstractInterceptor; -import com.opensymphony.xwork2.interceptor.PreResultListener; -import com.opensymphony.xwork2.util.AnnotationUtils; - -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Comparator; -import java.util.List; - -/** - * - *

    Invokes any annotated methods on the action. Specifically, it supports the following - * annotations:

    - *
      - *
    • @{@link Before} - will be invoked before the action method. If the returned value is not null, it is - * returned as the action result code
    • - *
    • @{@link BeforeResult} - will be invoked after the action method but before the result execution
    • - *
    • @{@link After} - will be invoked after the action method and result execution
    • - *
    - * - *

    There can be multiple methods marked with the same annotations, but the order of their execution - * is not guaranteed. However, the annotated methods on the superclass chain are guaranteed to be invoked before the - * annotated method in the current class in the case of a {@link Before} annotations and after, if the annotations is - * {@link After}.

    - * - * - *
    - * 
    - *  public class BaseAnnotatedAction {
    - *  	protected String log = "";
    - *
    - *  	@Before
    - *  	public String baseBefore() {
    - *  		log = log + "baseBefore-";
    - *  		return null;
    - *  	}
    - *  }
    - *
    - *  public class AnnotatedAction extends BaseAnnotatedAction {
    - *  	@Before
    - *  	public String before() {
    - *  		log = log + "before";
    - *  		return null;
    - *  	}
    - *
    - *  	public String execute() {
    - *  		log = log + "-execute";
    - *  		return Action.SUCCESS;
    - *  	}
    - *
    - *  	@BeforeResult
    - *  	public void beforeResult() throws Exception {
    - *  		log = log +"-beforeResult";
    - *  	}
    - *
    - *  	@After
    - *  	public void after() {
    - *  		log = log + "-after";
    - *  	}
    - *  }
    - * 
    - *  
    - * - * - *

    With the interceptor applied and the action executed on AnnotatedAction the log - * instance variable will contain baseBefore-before-execute-beforeResult-after.

    - * - * - *

    Configure a stack in xwork.xml that replaces the PrepareInterceptor with the AnnotationWorkflowInterceptor:

    - *
    - * 
    - * <interceptor-stack name="annotatedStack">
    - * 	<interceptor-ref name="staticParams"/>
    - * 	<interceptor-ref name="params"/>
    - * 	<interceptor-ref name="conversionError"/>
    - * 	<interceptor-ref name="annotationWorkflow"/>
    - * </interceptor-stack>
    - *  
    - * 
    - * - * @author Zsolt Szasz, zsolt at lorecraft dot com - * @author Rainer Hermanns - * @author Dan Oxlade, dan d0t oxlade at gmail d0t c0m - */ -public class AnnotationWorkflowInterceptor extends AbstractInterceptor implements PreResultListener { - - /** - * Discovers annotated methods on the action and calls them according to the workflow - * - * @see com.opensymphony.xwork2.interceptor.Interceptor#intercept(com.opensymphony.xwork2.ActionInvocation) - */ - public String intercept(ActionInvocation invocation) throws Exception { - final Object action = invocation.getAction(); - invocation.addPreResultListener(this); - List methods = new ArrayList<>(AnnotationUtils.getAnnotatedMethods(action.getClass(), Before.class)); - if (methods.size() > 0) { - // methods are only sorted by priority - Collections.sort(methods, new Comparator() { - public int compare(Method method1, Method method2) { - return comparePriorities(method1.getAnnotation(Before.class).priority(), - method2.getAnnotation(Before.class).priority()); - } - }); - for (Method m : methods) { - final String resultCode = (String) m.invoke(action, (Object[]) null); - if (resultCode != null) { - // shortcircuit execution - return resultCode; - } - } - } - - String invocationResult = invocation.invoke(); - - // invoke any @After methods - methods = new ArrayList(AnnotationUtils.getAnnotatedMethods(action.getClass(), After.class)); - - if (methods.size() > 0) { - // methods are only sorted by priority - Collections.sort(methods, new Comparator() { - public int compare(Method method1, Method method2) { - return comparePriorities(method1.getAnnotation(After.class).priority(), - method2.getAnnotation(After.class).priority()); - } - }); - for (Method m : methods) { - m.invoke(action, (Object[]) null); - } - } - - return invocationResult; - } - - protected static int comparePriorities(int val1, int val2) { - if (val2 < val1) { - return -1; - } else if (val2 > val1) { - return 1; - } else { - return 0; - } - } - - /** - * Invokes any @BeforeResult annotated methods - * - * @see com.opensymphony.xwork2.interceptor.PreResultListener#beforeResult(com.opensymphony.xwork2.ActionInvocation,String) - */ - public void beforeResult(ActionInvocation invocation, String resultCode) { - Object action = invocation.getAction(); - List methods = new ArrayList(AnnotationUtils.getAnnotatedMethods(action.getClass(), BeforeResult.class)); - - if (methods.size() > 0) { - // methods are only sorted by priority - Collections.sort(methods, new Comparator() { - public int compare(Method method1, Method method2) { - return comparePriorities(method1.getAnnotation(BeforeResult.class).priority(), - method2.getAnnotation(BeforeResult.class).priority()); - } - }); - for (Method m : methods) { - try { - m.invoke(action, (Object[]) null); - } catch (Exception e) { - throw new XWorkException(e); - } - } - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/Before.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/Before.java deleted file mode 100644 index abc2b510fe..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/Before.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * Marks a action method that needs to be executed before the main action method. - * - * - *

    Annotation usage:

    - * - * - * The Before annotation can be applied at method level. - * - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    priorityno10Priority order of method execution
    - * - * - *

    Example code:

    - * - *
    - * 
    - * public class SampleAction extends ActionSupport {
    - *
    - *  @Before
    - *  public void isAuthorized() throws AuthenticationException {
    - *    // authorize request, throw exception if failed
    - *  }
    - *
    - *  public String execute() {
    - *     // perform secure action
    - *     return SUCCESS;
    - *  }
    - * }
    - * 
    - * 
    - * - * @author Zsolt Szasz, zsolt at lorecraft dot com - * @author Rainer Hermanns - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface Before { - int priority() default 10; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/BeforeResult.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/BeforeResult.java deleted file mode 100644 index 84e15fa835..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/BeforeResult.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * Marks a action method that needs to be executed before the result. Return value is ignored. - * - * - *

    Annotation usage:

    - * - * - * The BeforeResult annotation can be applied at method level. - * - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    priorityno10Priority order of method execution
    - * - * - *

    Example code:

    - * - *
    - * 
    - * public class SampleAction extends ActionSupport {
    - *
    - *  @BeforeResult
    - *  public void isValid() throws ValidationException {
    - *    // validate model object, throw exception if failed
    - *  }
    - *
    - *  public String execute() {
    - *     // perform action
    - *     return SUCCESS;
    - *  }
    - * }
    - * 
    - * 
    - * - * @author Zsolt Szasz, zsolt at lorecraft dot com - * @author Rainer Hermanns - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface BeforeResult { - int priority() default 10; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/BlockByDefault.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/BlockByDefault.java deleted file mode 100644 index a87ac0b97c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/BlockByDefault.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.opensymphony.xwork2.interceptor.annotations; - -import com.opensymphony.xwork2.Action; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Declares that by default fields on the {@link Action} class - * are NOT permitted to be set from HttpRequest parameters. - * To allow access to a field it must be annotated with {@link Allowed} - * - * @author martin.gilday - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.TYPE) -public @interface BlockByDefault { - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/Blocked.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/Blocked.java deleted file mode 100644 index e9a288585b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/Blocked.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.opensymphony.xwork2.interceptor.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Declares that the given field should NOT be able to be mutated through - * a HttpRequest parameter. - * - * @author martin.gilday - */ -@Retention(RetentionPolicy.RUNTIME) -@Target(ElementType.FIELD) -public @interface Blocked { - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/InputConfig.java b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/InputConfig.java deleted file mode 100644 index 6ef8ee060e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/InputConfig.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2002-2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.interceptor.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -import com.opensymphony.xwork2.Action; - -/** - * - * Marks a action method that if it's not validated by ValidationInterceptor then execute input method or input result. - * - * - *

    Annotation usage:

    - * - * - * The InputConfig annotation can be applied at method level. - * - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    methodNamenoexecute this method if specific
    resultNamenoreturn this result if methodName not specific
    - * - * - *

    Example code:

    - * - *
    - * 
    - * public class SampleAction extends ActionSupport {
    - *
    - *  public void isValid() throws ValidationException {
    - *    // validate model object, throw exception if failed
    - *  }
    - *
    - *  @InputConfig(methodName="input")
    - *  public String execute() {
    - *     // perform action
    - *     return SUCCESS;
    - *  }
    - *  public String input() {
    - *     // perform some data filling
    - *     return INPUT;
    - *  }
    - * }
    - * 
    - * 
    - * - * @author zhouyanming, zhouyanming@gmail.com - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.METHOD}) -public @interface InputConfig { - String methodName() default ""; - String resultName() default Action.INPUT; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/package.html b/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/package.html deleted file mode 100644 index 8ac50a8b63..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/annotations/package.html +++ /dev/null @@ -1 +0,0 @@ -Interceptor annotations. diff --git a/core/src/main/java/com/opensymphony/xwork2/interceptor/package.html b/core/src/main/java/com/opensymphony/xwork2/interceptor/package.html deleted file mode 100644 index 505d814e07..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/interceptor/package.html +++ /dev/null @@ -1 +0,0 @@ -Interceptor classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/mock/MockActionInvocation.java b/core/src/main/java/com/opensymphony/xwork2/mock/MockActionInvocation.java deleted file mode 100644 index 074968905f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/mock/MockActionInvocation.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.mock; - -import com.opensymphony.xwork2.*; -import com.opensymphony.xwork2.interceptor.PreResultListener; -import com.opensymphony.xwork2.util.ValueStack; - -import java.util.ArrayList; -import java.util.List; - -/** - * Mock for an {@link ActionInvocation}. - * - * @author plightbo - * @author Rainer Hermanns - * @author tm_jee - * @version $Id$ - */ -public class MockActionInvocation implements ActionInvocation { - - private Object action; - private ActionContext invocationContext; - private ActionEventListener actionEventListener; - private ActionProxy proxy; - private Result result; - private String resultCode; - private ValueStack stack; - - private List preResultListeners = new ArrayList<>(); - - public Object getAction() { - return action; - } - - public void setAction(Object action) { - this.action = action; - } - - public ActionContext getInvocationContext() { - return invocationContext; - } - - public void setInvocationContext(ActionContext invocationContext) { - this.invocationContext = invocationContext; - } - - public ActionProxy getProxy() { - return proxy; - } - - public void setProxy(ActionProxy proxy) { - this.proxy = proxy; - } - - public Result getResult() { - return result; - } - - public void setResult(Result result) { - this.result = result; - } - - public String getResultCode() { - return resultCode; - } - - public void setResultCode(String resultCode) { - this.resultCode = resultCode; - } - - public ValueStack getStack() { - return stack; - } - - public void setStack(ValueStack stack) { - this.stack = stack; - } - - public boolean isExecuted() { - return false; - } - - public void addPreResultListener(PreResultListener listener) { - preResultListeners.add(listener); - } - - public String invoke() throws Exception { - for (Object preResultListener : preResultListeners) { - PreResultListener listener = (PreResultListener) preResultListener; - listener.beforeResult(this, resultCode); - } - return resultCode; - } - - public String invokeActionOnly() throws Exception { - return resultCode; - } - - public void setActionEventListener(ActionEventListener listener) { - this.actionEventListener = listener; - } - - public ActionEventListener getActionEventListener() { - return this.actionEventListener; - } - - public void init(ActionProxy proxy) { - } - - public ActionInvocation serialize() { - return this; - } - - public ActionInvocation deserialize(ActionContext actionContext) { - return this; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/mock/MockActionProxy.java b/core/src/main/java/com/opensymphony/xwork2/mock/MockActionProxy.java deleted file mode 100644 index f3735910ad..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/mock/MockActionProxy.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.mock; - -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.ActionProxy; -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import org.apache.commons.lang3.StringUtils; - -/** - * Mock for an {@link ActionProxy}. - * - * @author Patrick Lightbody (plightbo at gmail dot com) - */ -public class MockActionProxy implements ActionProxy { - - Object action; - String actionName; - ActionConfig config; - boolean executeResult; - ActionInvocation invocation; - String namespace; - String method; - boolean executedCalled; - String returnedResult; - Configuration configuration; - boolean methodSpecified; - - public void prepare() throws Exception {} - - public String execute() throws Exception { - executedCalled = true; - - return returnedResult; - } - - public void setReturnedResult(String returnedResult) { - this.returnedResult = returnedResult; - } - - public boolean isExecutedCalled() { - return executedCalled; - } - - public Object getAction() { - return action; - } - - public void setAction(Object action) { - this.action = action; - } - - public String getActionName() { - return actionName; - } - - public void setActionName(String actionName) { - this.actionName = actionName; - } - - public ActionConfig getConfig() { - return config; - } - - public void setConfig(ActionConfig config) { - this.config = config; - } - - public boolean getExecuteResult() { - return executeResult; - } - - public void setExecuteResult(boolean executeResult) { - this.executeResult = executeResult; - } - - public ActionInvocation getInvocation() { - return invocation; - } - - public void setInvocation(ActionInvocation invocation) { - this.invocation = invocation; - } - - public String getNamespace() { - return namespace; - } - - public void setNamespace(String namespace) { - this.namespace = namespace; - } - - public String getMethod() { - return method; - } - - public void setMethod(String method) { - this.method = method; - methodSpecified = StringUtils.isNotEmpty(method); - } - - public boolean isMethodSpecified() - { - return methodSpecified; - } - - public void setMethodSpecified(boolean methodSpecified) - { - this.methodSpecified = methodSpecified; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/mock/MockContainer.java b/core/src/main/java/com/opensymphony/xwork2/mock/MockContainer.java deleted file mode 100644 index bcad8a9751..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/mock/MockContainer.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.opensymphony.xwork2.mock; - -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Scope; - -import java.util.Set; - -/** - * Mock implementation to be used in unittests - */ -public class MockContainer implements Container { - - public void inject(Object o) { - - } - - public T inject(Class implementation) { - return null; - } - - public T getInstance(Class type, String name) { - return null; - } - - public T getInstance(Class type) { - return null; - } - - public Set getInstanceNames(Class type) { - return null; - } - - public void setScopeStrategy(Scope.Strategy scopeStrategy) { - - } - - public void removeScopeStrategy() { - - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/mock/MockInterceptor.java b/core/src/main/java/com/opensymphony/xwork2/mock/MockInterceptor.java deleted file mode 100644 index b6488364d4..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/mock/MockInterceptor.java +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.mock; - -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.interceptor.AbstractInterceptor; -import org.junit.Assert; - -/** - * Mock for an {@link com.opensymphony.xwork2.interceptor.Interceptor}. - * - * @author Jason Carreira - */ -public class MockInterceptor extends AbstractInterceptor { - - private static final long serialVersionUID = 2692551676567227756L; - - public static final String DEFAULT_FOO_VALUE = "fooDefault"; - - - private String expectedFoo = DEFAULT_FOO_VALUE; - private String foo = DEFAULT_FOO_VALUE; - private boolean executed = false; - - - public boolean isExecuted() { - return executed; - } - - public void setExpectedFoo(String expectedFoo) { - this.expectedFoo = expectedFoo; - } - - public String getExpectedFoo() { - return expectedFoo; - } - - public void setFoo(String foo) { - this.foo = foo; - } - - public String getFoo() { - return foo; - } - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - if (!(o instanceof MockInterceptor)) { - return false; - } - - final MockInterceptor testInterceptor = (MockInterceptor) o; - - if (executed != testInterceptor.executed) { - return false; - } - - if ((expectedFoo != null) ? (!expectedFoo.equals(testInterceptor.expectedFoo)) : (testInterceptor.expectedFoo != null)) - { - return false; - } - - if ((foo != null) ? (!foo.equals(testInterceptor.foo)) : (testInterceptor.foo != null)) { - return false; - } - - return true; - } - - @Override - public int hashCode() { - int result; - result = ((expectedFoo != null) ? expectedFoo.hashCode() : 0); - result = (29 * result) + ((foo != null) ? foo.hashCode() : 0); - result = (29 * result) + (executed ? 1 : 0); - - return result; - } - - /** - * Allows the Interceptor to do some processing on the request before and/or after the rest of the processing of the - * request by the DefaultActionInvocation or to short-circuit the processing and just return a String return code. - */ - public String intercept(ActionInvocation invocation) throws Exception { - executed = true; - Assert.assertNotSame(DEFAULT_FOO_VALUE, foo); - Assert.assertEquals(expectedFoo, foo); - - return invocation.invoke(); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/mock/MockObjectTypeDeterminer.java b/core/src/main/java/com/opensymphony/xwork2/mock/MockObjectTypeDeterminer.java deleted file mode 100644 index f01261a809..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/mock/MockObjectTypeDeterminer.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.mock; - -import com.opensymphony.xwork2.conversion.ObjectTypeDeterminer; -import ognl.OgnlException; -import ognl.OgnlRuntime; - -import java.util.Map; - -/** - * Mocks the function of an ObjectTypeDeterminer for testing purposes. - * - * @author Gabe - */ -public class MockObjectTypeDeterminer implements ObjectTypeDeterminer { - - private Class keyClass; - private Class elementClass; - private String keyProperty; - private boolean shouldCreateIfNew; - - public MockObjectTypeDeterminer() {} - - - /** - * @param keyClass key class - * @param elementClass element class - * @param keyProperty key property - * @param shouldCreateIfNew create if new - */ - public MockObjectTypeDeterminer(Class keyClass, Class elementClass, - String keyProperty, boolean shouldCreateIfNew) { - super(); - this.keyClass = keyClass; - this.elementClass = elementClass; - this.keyProperty = keyProperty; - this.shouldCreateIfNew = shouldCreateIfNew; - } - - public Class getKeyClass(Class parentClass, String property) { - return getKeyClass(); - } - - public Class getElementClass(Class parentClass, String property, Object key) { - return getElementClass(); - } - - public String getKeyProperty(Class parentClass, String property) { - return getKeyProperty(); - } - - public boolean shouldCreateIfNew(Class parentClass, String property, - Object target, String keyProperty, boolean isIndexAccessed) { - try { - System.out.println("ognl:"+OgnlRuntime.getPropertyAccessor(Map.class)+" this:"+this); - } catch (OgnlException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - return isShouldCreateIfNew(); - } - - /** - * @return Returns the elementClass. - */ - public Class getElementClass() { - return elementClass; - } - /** - * @param elementClass The elementClass to set. - */ - public void setElementClass(Class elementClass) { - this.elementClass = elementClass; - } - /** - * @return Returns the keyClass. - */ - public Class getKeyClass() { - return keyClass; - } - /** - * @param keyClass The keyClass to set. - */ - public void setKeyClass(Class keyClass) { - this.keyClass = keyClass; - } - /** - * @return Returns the keyProperty. - */ - public String getKeyProperty() { - return keyProperty; - } - /** - * @param keyProperty The keyProperty to set. - */ - public void setKeyProperty(String keyProperty) { - this.keyProperty = keyProperty; - } - /** - * @return Returns the shouldCreateIfNew. - */ - public boolean isShouldCreateIfNew() { - return shouldCreateIfNew; - } - /** - * @param shouldCreateIfNew The shouldCreateIfNew to set. - */ - public void setShouldCreateIfNew(boolean shouldCreateIfNew) { - this.shouldCreateIfNew = shouldCreateIfNew; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/mock/MockResult.java b/core/src/main/java/com/opensymphony/xwork2/mock/MockResult.java deleted file mode 100644 index 571469cb76..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/mock/MockResult.java +++ /dev/null @@ -1,53 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.mock; - -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.Result; - -/** - * Mock for a {@link Result}. - * - * @author Mike - * @author Rainer Hermanns - */ -public class MockResult implements Result { - - public static final String DEFAULT_PARAM = "foo"; - - @Override - public boolean equals(Object o) { - if (this == o) { - return true; - } - - return o instanceof MockResult; - } - - public void execute(ActionInvocation invocation) throws Exception { - // no op - } - - @Override - public int hashCode() { - return 10; - } - - public void setFoo(String foo) { - // no op - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/mock/package.html b/core/src/main/java/com/opensymphony/xwork2/mock/package.html deleted file mode 100644 index 61bdf48e92..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/mock/package.html +++ /dev/null @@ -1 +0,0 @@ -XWork specific mock classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/ErrorMessageBuilder.java b/core/src/main/java/com/opensymphony/xwork2/ognl/ErrorMessageBuilder.java deleted file mode 100644 index e136241a16..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/ErrorMessageBuilder.java +++ /dev/null @@ -1,58 +0,0 @@ -package com.opensymphony.xwork2.ognl; - -/** - * Helper class to build error messages. - */ -public class ErrorMessageBuilder { - - private StringBuilder message = new StringBuilder(); - - public static ErrorMessageBuilder create() { - return new ErrorMessageBuilder(); - } - - private ErrorMessageBuilder() { - } - - public ErrorMessageBuilder errorSettingExpressionWithValue(String expr, Object value) { - appenExpression(expr); - if (value instanceof Object[]) { - appendValueAsArray((Object[]) value, message); - } else { - appendValue(value); - } - return this; - } - - private void appenExpression(String expr) { - message.append("Error setting expression '"); - message.append(expr); - message.append("' with value "); - } - - private void appendValue(Object value) { - message.append("'"); - message.append(value); - message.append("'"); - } - - private void appendValueAsArray(Object[] valueArray, StringBuilder msg) { - msg.append("["); - for (int index = 0; index < valueArray.length; index++) { - appendValue(valueArray[index]); - if (hasMoreElements(valueArray, index)) { - msg.append(", "); - } - } - msg.append("]"); - } - - private boolean hasMoreElements(Object[] valueArray, int index) { - return index < (valueArray.length + 1); - } - - public String build() { - return message.toString(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/ObjectProxy.java b/core/src/main/java/com/opensymphony/xwork2/ognl/ObjectProxy.java deleted file mode 100644 index b01fd6736f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/ObjectProxy.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.ognl; - -/** - * An Object to use within OGNL to proxy other Objects - * usually Collections that you set in a different place - * on the ValueStack but want to retain the context information - * about where they previously were. - * - * @author Gabe - */ -public class ObjectProxy { - private Object value; - private Class lastClassAccessed; - private String lastPropertyAccessed; - - public Class getLastClassAccessed() { - return lastClassAccessed; - } - - public void setLastClassAccessed(Class lastClassAccessed) { - this.lastClassAccessed = lastClassAccessed; - } - - public String getLastPropertyAccessed() { - return lastPropertyAccessed; - } - - public void setLastPropertyAccessed(String lastPropertyAccessed) { - this.lastPropertyAccessed = lastPropertyAccessed; - } - - public Object getValue() { - return value; - } - - public void setValue(Object value) { - this.value = value; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlNullHandlerWrapper.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlNullHandlerWrapper.java deleted file mode 100644 index 95a0e35a2c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlNullHandlerWrapper.java +++ /dev/null @@ -1,24 +0,0 @@ -package com.opensymphony.xwork2.ognl; - -import com.opensymphony.xwork2.conversion.NullHandler; - -import java.util.Map; - -public class OgnlNullHandlerWrapper implements ognl.NullHandler { - - private NullHandler wrapped; - - public OgnlNullHandlerWrapper(NullHandler target) { - this.wrapped = target; - } - - public Object nullMethodResult(Map context, Object target, - String methodName, Object[] args) { - return wrapped.nullMethodResult(context, target, methodName, args); - } - - public Object nullPropertyValue(Map context, Object target, Object property) { - return wrapped.nullPropertyValue(context, target, property); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionContextFactory.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionContextFactory.java deleted file mode 100644 index 03a5537f14..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionContextFactory.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.opensymphony.xwork2.ognl; - -import com.opensymphony.xwork2.util.reflection.ReflectionContextFactory; -import ognl.Ognl; - -import java.util.Map; - -public class OgnlReflectionContextFactory implements ReflectionContextFactory { - - public Map createDefaultContext(Object root) { - return Ognl.createDefaultContext(root); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionProvider.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionProvider.java deleted file mode 100644 index 34f304343c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlReflectionProvider.java +++ /dev/null @@ -1,125 +0,0 @@ -package com.opensymphony.xwork2.ognl; - -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.reflection.ReflectionException; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; -import ognl.Ognl; -import ognl.OgnlException; -import ognl.OgnlRuntime; - -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Collection; -import java.util.Map; - -public class OgnlReflectionProvider implements ReflectionProvider { - - private OgnlUtil ognlUtil; - - @Inject - public void setOgnlUtil(OgnlUtil ognlUtil) { - this.ognlUtil = ognlUtil; - } - - public Field getField(Class inClass, String name) { - return OgnlRuntime.getField(inClass, name); - } - - public Method getGetMethod(Class targetClass, String propertyName) - throws IntrospectionException, ReflectionException { - try { - return OgnlRuntime.getGetMethod(null, targetClass, propertyName); - } catch (OgnlException e) { - throw new ReflectionException(e); - } - } - - public Method getSetMethod(Class targetClass, String propertyName) - throws IntrospectionException, ReflectionException { - try { - return OgnlRuntime.getSetMethod(null, targetClass, propertyName); - } catch (OgnlException e) { - throw new ReflectionException(e); - } - } - - public void setProperties(Map props, Object o, Map context) { - ognlUtil.setProperties(props, o, context); - } - - public void setProperties(Map props, Object o, Map context, boolean throwPropertyExceptions) throws ReflectionException{ - ognlUtil.setProperties(props, o, context, throwPropertyExceptions); - - } - - public void setProperties(Map properties, Object o) { - ognlUtil.setProperties(properties, o); - } - - public PropertyDescriptor getPropertyDescriptor(Class targetClass, - String propertyName) throws IntrospectionException, - ReflectionException { - try { - return OgnlRuntime.getPropertyDescriptor(targetClass, propertyName); - } catch (OgnlException e) { - throw new ReflectionException(e); - } - } - - public void copy(Object from, Object to, Map context, - Collection exclusions, Collection inclusions) { - ognlUtil.copy(from, to, context, exclusions, inclusions); - } - - public Object getRealTarget(String property, Map context, Object root) - throws ReflectionException { - try { - return ognlUtil.getRealTarget(property, context, root); - } catch (OgnlException e) { - throw new ReflectionException(e); - } - } - - public void setProperty(String name, Object value, Object o, Map context) { - ognlUtil.setProperty(name, value, o, context); - } - - public void setProperty(String name, Object value, Object o, Map context, boolean throwPropertyExceptions) { - ognlUtil.setProperty(name, value, o, context, throwPropertyExceptions); - } - - public Map getBeanMap(Object source) throws IntrospectionException, - ReflectionException { - try { - return ognlUtil.getBeanMap(source); - } catch (OgnlException e) { - throw new ReflectionException(e); - } - } - - public Object getValue(String expression, Map context, Object root) - throws ReflectionException { - try { - return ognlUtil.getValue(expression, context, root); - } catch (OgnlException e) { - throw new ReflectionException(e); - } - } - - public void setValue(String expression, Map context, Object root, - Object value) throws ReflectionException { - try { - Ognl.setValue(expression, context, root, value); - } catch (OgnlException e) { - throw new ReflectionException(e); - } - } - - public PropertyDescriptor[] getPropertyDescriptors(Object source) - throws IntrospectionException { - return ognlUtil.getPropertyDescriptors(source); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlTypeConverterWrapper.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlTypeConverterWrapper.java deleted file mode 100644 index ad79542cc8..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlTypeConverterWrapper.java +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl; - -import com.opensymphony.xwork2.conversion.TypeConverter; - -import java.lang.reflect.Member; -import java.util.Map; - -/** - * Wraps an XWork type conversion class for as an OGNL TypeConverter - */ -public class OgnlTypeConverterWrapper implements ognl.TypeConverter { - - private TypeConverter typeConverter; - - public OgnlTypeConverterWrapper(TypeConverter converter) { - if (converter == null) { - throw new IllegalArgumentException("Wrapped type converter cannot be null"); - } - this.typeConverter = converter; - } - - public Object convertValue(Map context, Object target, Member member, - String propertyName, Object value, Class toType) { - return typeConverter.convertValue(context, target, member, propertyName, value, toType); - } - - public TypeConverter getTarget() { - return typeConverter; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java deleted file mode 100644 index 86e9c5354c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlUtil.java +++ /dev/null @@ -1,658 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl; - -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.conversion.impl.XWorkConverter; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor; -import com.opensymphony.xwork2.util.CompoundRoot; -import com.opensymphony.xwork2.util.TextParseUtil; -import com.opensymphony.xwork2.util.reflection.ReflectionException; -import ognl.*; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.beans.BeanInfo; -import java.beans.IntrospectionException; -import java.beans.Introspector; -import java.beans.PropertyDescriptor; -import java.lang.reflect.Method; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.regex.Pattern; - - -/** - * Utility class that provides common access to the Ognl APIs for - * setting and getting properties from objects (usually Actions). - * - * @author Jason Carreira - */ -public class OgnlUtil { - - private static final Logger LOG = LogManager.getLogger(OgnlUtil.class); - private ConcurrentMap expressions = new ConcurrentHashMap<>(); - private final ConcurrentMap beanInfoCache = new ConcurrentHashMap<>(); - private TypeConverter defaultConverter; - - private boolean devMode = false; - private boolean enableExpressionCache = true; - private boolean enableEvalExpression; - - private Set> excludedClasses = new HashSet<>(); - private Set excludedPackageNamePatterns = new HashSet<>(); - private Set excludedPackageNames = new HashSet<>(); - - private Container container; - private boolean allowStaticMethodAccess; - - @Inject - public void setXWorkConverter(XWorkConverter conv) { - this.defaultConverter = new OgnlTypeConverterWrapper(conv); - } - - @Inject(XWorkConstants.DEV_MODE) - public void setDevMode(String mode) { - this.devMode = BooleanUtils.toBoolean(mode); - } - - @Inject(XWorkConstants.ENABLE_OGNL_EXPRESSION_CACHE) - public void setEnableExpressionCache(String cache) { - enableExpressionCache = BooleanUtils.toBoolean(cache); - } - - @Inject(value = XWorkConstants.ENABLE_OGNL_EVAL_EXPRESSION, required = false) - public void setEnableEvalExpression(String evalExpression) { - enableEvalExpression = "true".equals(evalExpression); - if(enableEvalExpression){ - LOG.warn("Enabling OGNL expression evaluation may introduce security risks " + - "(see http://struts.apache.org/release/2.3.x/docs/s2-013.html for further details)"); - } - } - - @Inject(value = XWorkConstants.OGNL_EXCLUDED_CLASSES, required = false) - public void setExcludedClasses(String commaDelimitedClasses) { - Set classes = TextParseUtil.commaDelimitedStringToSet(commaDelimitedClasses); - for (String className : classes) { - try { - excludedClasses.add(Class.forName(className)); - } catch (ClassNotFoundException e) { - throw new ConfigurationException("Cannot load excluded class: " + className, e); - } - } - } - - @Inject(value = XWorkConstants.OGNL_EXCLUDED_PACKAGE_NAME_PATTERNS, required = false) - public void setExcludedPackageNamePatterns(String commaDelimitedPackagePatterns) { - Set packagePatterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPackagePatterns); - for (String pattern : packagePatterns) { - excludedPackageNamePatterns.add(Pattern.compile(pattern)); - } - } - - @Inject(value = XWorkConstants.OGNL_EXCLUDED_PACKAGE_NAMES, required = false) - public void setExcludedPackageNames(String commaDelimitedPackageNames) { - excludedPackageNames = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPackageNames); - } - - public Set> getExcludedClasses() { - return excludedClasses; - } - - public Set getExcludedPackageNamePatterns() { - return excludedPackageNamePatterns; - } - - public Set getExcludedPackageNames() { - return excludedPackageNames; - } - - @Inject - public void setContainer(Container container) { - this.container = container; - } - - @Inject(value = XWorkConstants.ALLOW_STATIC_METHOD_ACCESS, required = false) - public void setAllowStaticMethodAccess(String allowStaticMethodAccess) { - this.allowStaticMethodAccess = Boolean.parseBoolean(allowStaticMethodAccess); - } - - /** - * Sets the object's properties using the default type converter, defaulting to not throw - * exceptions for problems setting the properties. - * - * @param props the properties being set - * @param o the object - * @param context the action context - */ - public void setProperties(Map props, Object o, Map context) { - setProperties(props, o, context, false); - } - - /** - * Sets the object's properties using the default type converter. - * - * @param props the properties being set - * @param o the object - * @param context the action context - * @param throwPropertyExceptions boolean which tells whether it should throw exceptions for - * problems setting the properties - */ - public void setProperties(Map props, Object o, Map context, boolean throwPropertyExceptions) throws ReflectionException{ - if (props == null) { - return; - } - - Ognl.setTypeConverter(context, getTypeConverterFromContext(context)); - - Object oldRoot = Ognl.getRoot(context); - Ognl.setRoot(context, o); - - for (Map.Entry entry : props.entrySet()) { - String expression = entry.getKey(); - internalSetProperty(expression, entry.getValue(), o, context, throwPropertyExceptions); - } - - Ognl.setRoot(context, oldRoot); - } - - /** - * Sets the properties on the object using the default context, defaulting to not throwing - * exceptions for problems setting the properties. - * - * @param properties map of properties - * @param o object - */ - public void setProperties(Map properties, Object o) { - setProperties(properties, o, false); - } - - /** - * Sets the properties on the object using the default context. - * - * @param properties the property map to set on the object - * @param o the object to set the properties into - * @param throwPropertyExceptions boolean which tells whether it should throw exceptions for - * problems setting the properties - */ - public void setProperties(Map properties, Object o, boolean throwPropertyExceptions) { - Map context = createDefaultContext(o, null); - setProperties(properties, o, context, throwPropertyExceptions); - } - - /** - * Sets the named property to the supplied value on the Object, defaults to not throwing - * property exceptions. - * - * @param name the name of the property to be set - * @param value the value to set into the named property - * @param o the object upon which to set the property - * @param context the context which may include the TypeConverter - */ - public void setProperty(String name, Object value, Object o, Map context) { - setProperty(name, value, o, context, false); - } - - /** - * Sets the named property to the supplied value on the Object. - * - * @param name the name of the property to be set - * @param value the value to set into the named property - * @param o the object upon which to set the property - * @param context the context which may include the TypeConverter - * @param throwPropertyExceptions boolean which tells whether it should throw exceptions for - * problems setting the property - */ - public void setProperty(String name, Object value, Object o, Map context, boolean throwPropertyExceptions) { - Ognl.setTypeConverter(context, getTypeConverterFromContext(context)); - - Object oldRoot = Ognl.getRoot(context); - Ognl.setRoot(context, o); - - internalSetProperty(name, value, o, context, throwPropertyExceptions); - - Ognl.setRoot(context, oldRoot); - } - - /** - * Looks for the real target with the specified property given a root Object which may be a - * CompoundRoot. - * - * @param property the property - * @param context context map - * @param root compound root - * - * @return the real target or null if no object can be found with the specified property - * @throws OgnlException in case of ognl errors - */ - public Object getRealTarget(String property, Map context, Object root) throws OgnlException { - //special keyword, they must be cutting the stack - if ("top".equals(property)) { - return root; - } - - if (root instanceof CompoundRoot) { - // find real target - CompoundRoot cr = (CompoundRoot) root; - - try { - for (Object target : cr) { - if (OgnlRuntime.hasSetProperty((OgnlContext) context, target, property) - || OgnlRuntime.hasGetProperty((OgnlContext) context, target, property) - || OgnlRuntime.getIndexedPropertyType((OgnlContext) context, target.getClass(), property) != OgnlRuntime.INDEXED_PROPERTY_NONE - ) { - return target; - } - } - } catch (IntrospectionException ex) { - throw new ReflectionException("Cannot figure out real target class", ex); - } - - return null; - } - - return root; - } - - /** - * Wrapper around Ognl.setValue() to handle type conversion for collection elements. - * Ideally, this should be handled by OGNL directly. - * - * @param name the name - * @param context context map - * @param root root - * @param value value - * - * @throws OgnlException in case of ognl errors - */ - public void setValue(final String name, final Map context, final Object root, final Object value) throws OgnlException { - compileAndExecute(name, context, new OgnlTask() { - public Void execute(Object tree) throws OgnlException { - if (isEvalExpression(tree, context)) { - throw new OgnlException("Eval expression/chained expressions cannot be used as parameter name"); - } - if (isArithmeticExpression(tree, context)) { - throw new OgnlException("Arithmetic expressions cannot be used as parameter name"); - } - Ognl.setValue(tree, context, root, value); - return null; - } - }); - } - - private boolean isEvalExpression(Object tree, Map context) throws OgnlException { - if (tree instanceof SimpleNode) { - SimpleNode node = (SimpleNode) tree; - OgnlContext ognlContext = null; - - if (context!=null && context instanceof OgnlContext) { - ognlContext = (OgnlContext) context; - } - return node.isEvalChain(ognlContext) || node.isSequence(ognlContext); - } - return false; - } - - private boolean isArithmeticExpression(Object tree, Map context) throws OgnlException { - if (tree instanceof SimpleNode) { - SimpleNode node = (SimpleNode) tree; - OgnlContext ognlContext = null; - - if (context!=null && context instanceof OgnlContext) { - ognlContext = (OgnlContext) context; - } - return node.isOperation(ognlContext); - } - return false; - } - - private boolean isSimpleMethod(Object tree, Map context) throws OgnlException { - if (tree instanceof SimpleNode) { - SimpleNode node = (SimpleNode) tree; - OgnlContext ognlContext = null; - - if (context!=null && context instanceof OgnlContext) { - ognlContext = (OgnlContext) context; - } - return node.isSimpleMethod(ognlContext) && !node.isChain(ognlContext); - } - return false; - } - - public Object getValue(final String name, final Map context, final Object root) throws OgnlException { - return compileAndExecute(name, context, new OgnlTask() { - public Object execute(Object tree) throws OgnlException { - return Ognl.getValue(tree, context, root); - } - }); - } - - public Object callMethod(final String name, final Map context, final Object root) throws OgnlException { - return compileAndExecuteMethod(name, context, new OgnlTask() { - public Object execute(Object tree) throws OgnlException { - return Ognl.getValue(tree, context, root); - } - }); - } - - public Object getValue(final String name, final Map context, final Object root, final Class resultType) throws OgnlException { - return compileAndExecute(name, context, new OgnlTask() { - public Object execute(Object tree) throws OgnlException { - return Ognl.getValue(tree, context, root, resultType); - } - }); - } - - - public Object compile(String expression) throws OgnlException { - return compile(expression, null); - } - - private Object compileAndExecute(String expression, Map context, OgnlTask task) throws OgnlException { - Object tree; - if (enableExpressionCache) { - tree = expressions.get(expression); - if (tree == null) { - tree = Ognl.parseExpression(expression); - checkEnableEvalExpression(tree, context); - } - } else { - tree = Ognl.parseExpression(expression); - checkEnableEvalExpression(tree, context); - } - - final T exec = task.execute(tree); - // if cache is enabled and it's a valid expression, puts it in - if(enableExpressionCache) { - expressions.putIfAbsent(expression, tree); - } - return exec; - } - - private Object compileAndExecuteMethod(String expression, Map context, OgnlTask task) throws OgnlException { - Object tree; - if (enableExpressionCache) { - tree = expressions.get(expression); - if (tree == null) { - tree = Ognl.parseExpression(expression); - checkSimpleMethod(tree, context); - } - } else { - tree = Ognl.parseExpression(expression); - checkSimpleMethod(tree, context); - } - - final T exec = task.execute(tree); - // if cache is enabled and it's a valid expression, puts it in - if(enableExpressionCache) { - expressions.putIfAbsent(expression, tree); - } - return exec; - } - - public Object compile(String expression, Map context) throws OgnlException { - return compileAndExecute(expression,context,new OgnlTask() { - public Object execute(Object tree) throws OgnlException { - return tree; - } - }); - } - - private void checkEnableEvalExpression(Object tree, Map context) throws OgnlException { - if (!enableEvalExpression && isEvalExpression(tree, context)) { - throw new OgnlException("Eval expressions/chained expressions have been disabled!"); - } - } - - private void checkSimpleMethod(Object tree, Map context) throws OgnlException { - if (!isSimpleMethod(tree, context)) { - throw new OgnlException("It isn't a simple method which can be called!"); - } - } - - /** - * Copies the properties in the object "from" and sets them in the object "to" - * using specified type converter, or {@link com.opensymphony.xwork2.conversion.impl.XWorkConverter} if none - * is specified. - * - * @param from the source object - * @param to the target object - * @param context the action context we're running under - * @param exclusions collection of method names to excluded from copying ( can be null) - * @param inclusions collection of method names to included copying (can be null) - * note if exclusions AND inclusions are supplied and not null nothing will get copied. - */ - public void copy(final Object from, final Object to, final Map context, Collection exclusions, Collection inclusions) { - if (from == null || to == null) { - LOG.warn("Attempting to copy from or to a null source. This is illegal and is bein skipped. This may be due to an error in an OGNL expression, action chaining, or some other event."); - return; - } - - TypeConverter converter = getTypeConverterFromContext(context); - final Map contextFrom = createDefaultContext(from, null); - Ognl.setTypeConverter(contextFrom, converter); - final Map contextTo = createDefaultContext(to, null); - Ognl.setTypeConverter(contextTo, converter); - - PropertyDescriptor[] fromPds; - PropertyDescriptor[] toPds; - - try { - fromPds = getPropertyDescriptors(from); - toPds = getPropertyDescriptors(to); - } catch (IntrospectionException e) { - LOG.error("An error occurred", e); - return; - } - - Map toPdHash = new HashMap<>(); - - for (PropertyDescriptor toPd : toPds) { - toPdHash.put(toPd.getName(), toPd); - } - - for (PropertyDescriptor fromPd : fromPds) { - if (fromPd.getReadMethod() != null) { - boolean copy = true; - if (exclusions != null && exclusions.contains(fromPd.getName())) { - copy = false; - } else if (inclusions != null && !inclusions.contains(fromPd.getName())) { - copy = false; - } - - if (copy) { - PropertyDescriptor toPd = toPdHash.get(fromPd.getName()); - if ((toPd != null) && (toPd.getWriteMethod() != null)) { - try { - compileAndExecute(fromPd.getName(), context, new OgnlTask() { - public Void execute(Object expr) throws OgnlException { - Object value = Ognl.getValue(expr, contextFrom, from); - Ognl.setValue(expr, contextTo, to, value); - return null; - } - }); - - } catch (OgnlException e) { - LOG.debug("Got OGNL exception", e); - } - } - - } - - } - - } - } - - - /** - * Copies the properties in the object "from" and sets them in the object "to" - * using specified type converter, or {@link com.opensymphony.xwork2.conversion.impl.XWorkConverter} if none - * is specified. - * - * @param from the source object - * @param to the target object - * @param context the action context we're running under - */ - public void copy(Object from, Object to, Map context) { - copy(from, to, context, null, null); - } - - /** - * Get's the java beans property descriptors for the given source. - * - * @param source the source object. - * @return property descriptors. - * @throws IntrospectionException is thrown if an exception occurs during introspection. - */ - public PropertyDescriptor[] getPropertyDescriptors(Object source) throws IntrospectionException { - BeanInfo beanInfo = getBeanInfo(source); - return beanInfo.getPropertyDescriptors(); - } - - - /** - * Get's the java beans property descriptors for the given class. - * - * @param clazz the source object. - * @return property descriptors. - * @throws IntrospectionException is thrown if an exception occurs during introspection. - */ - public PropertyDescriptor[] getPropertyDescriptors(Class clazz) throws IntrospectionException { - BeanInfo beanInfo = getBeanInfo(clazz); - return beanInfo.getPropertyDescriptors(); - } - - /** - * Creates a Map with read properties for the given source object. - *

    - * If the source object does not have a read property (i.e. write-only) then - * the property is added to the map with the value here is no read method for property-name. - *

    - * - * @param source the source object. - * @return a Map with (key = read property name, value = value of read property). - * @throws IntrospectionException is thrown if an exception occurs during introspection. - * @throws OgnlException is thrown by OGNL if the property value could not be retrieved - */ - public Map getBeanMap(final Object source) throws IntrospectionException, OgnlException { - Map beanMap = new HashMap<>(); - final Map sourceMap = createDefaultContext(source, null); - PropertyDescriptor[] propertyDescriptors = getPropertyDescriptors(source); - for (PropertyDescriptor propertyDescriptor : propertyDescriptors) { - final String propertyName = propertyDescriptor.getDisplayName(); - Method readMethod = propertyDescriptor.getReadMethod(); - if (readMethod != null) { - final Object value = compileAndExecute(propertyName, null, new OgnlTask() { - public Object execute(Object expr) throws OgnlException { - return Ognl.getValue(expr, sourceMap, source); - } - }); - beanMap.put(propertyName, value); - } else { - beanMap.put(propertyName, "There is no read method for " + propertyName); - } - } - return beanMap; - } - - /** - * Get's the java bean info for the given source object. Calls getBeanInfo(Class c). - * - * @param from the source object. - * @return java bean info. - * @throws IntrospectionException is thrown if an exception occurs during introspection. - */ - public BeanInfo getBeanInfo(Object from) throws IntrospectionException { - return getBeanInfo(from.getClass()); - } - - - /** - * Get's the java bean info for the given source. - * - * @param clazz the source class. - * @return java bean info. - * @throws IntrospectionException is thrown if an exception occurs during introspection. - */ - public BeanInfo getBeanInfo(Class clazz) throws IntrospectionException { - synchronized (beanInfoCache) { - BeanInfo beanInfo; - beanInfo = beanInfoCache.get(clazz); - if (beanInfo == null) { - beanInfo = Introspector.getBeanInfo(clazz, Object.class); - beanInfoCache.putIfAbsent(clazz, beanInfo); - } - return beanInfo; - } - } - - void internalSetProperty(String name, Object value, Object o, Map context, boolean throwPropertyExceptions) throws ReflectionException{ - try { - setValue(name, context, o, value); - } catch (OgnlException e) { - Throwable reason = e.getReason(); - String msg = "Caught OgnlException while setting property '" + name + "' on type '" + o.getClass().getName() + "'."; - Throwable exception = (reason == null) ? e : reason; - - if (throwPropertyExceptions) { - throw new ReflectionException(msg, exception); - } else if (devMode) { - LOG.warn(msg, exception); - } - } - } - - TypeConverter getTypeConverterFromContext(Map context) { - /*ValueStack stack = (ValueStack) context.get(ActionContext.VALUE_STACK); - Container cont = (Container)stack.getContext().get(ActionContext.CONTAINER); - if (cont != null) { - return new OgnlTypeConverterWrapper(cont.getInstance(XWorkConverter.class)); - } else { - throw new IllegalArgumentException("Cannot find type converter in context map"); - } - */ - return defaultConverter; - } - - protected Map createDefaultContext(Object root) { - return createDefaultContext(root, null); - } - - protected Map createDefaultContext(Object root, ClassResolver classResolver) { - ClassResolver resolver = classResolver; - if (resolver == null) { - resolver = container.getInstance(CompoundRootAccessor.class); - } - - SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticMethodAccess); - memberAccess.setExcludedClasses(excludedClasses); - memberAccess.setExcludedPackageNamePatterns(excludedPackageNamePatterns); - memberAccess.setExcludedPackageNames(excludedPackageNames); - - return Ognl.createDefaultContext(root, resolver, defaultConverter, memberAccess); - } - - private interface OgnlTask { - T execute(Object tree) throws OgnlException; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStack.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStack.java deleted file mode 100644 index 28bef547d7..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStack.java +++ /dev/null @@ -1,477 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.TextProvider; -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.XWorkException; -import com.opensymphony.xwork2.conversion.impl.XWorkConverter; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor; -import com.opensymphony.xwork2.util.ClearableValueStack; -import com.opensymphony.xwork2.util.CompoundRoot; -import com.opensymphony.xwork2.util.MemberAccessValueStack; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.util.reflection.ReflectionContextState; -import ognl.*; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.Serializable; -import java.util.HashMap; -import java.util.Map; -import java.util.Set; -import java.util.regex.Pattern; - -/** - * Ognl implementation of a value stack that allows for dynamic Ognl expressions to be evaluated against it. When evaluating an expression, - * the stack will be searched down the stack, from the latest objects pushed in to the earliest, looking for a bean with a getter or setter - * for the given property or a method of the given name (depending on the expression being evaluated). - * - * @author Patrick Lightbody - * @author tm_jee - * @version $Date$ $Id$ - */ -public class OgnlValueStack implements Serializable, ValueStack, ClearableValueStack, MemberAccessValueStack { - - public static final String THROW_EXCEPTION_ON_FAILURE = OgnlValueStack.class.getName() + ".throwExceptionOnFailure"; - - private static final Logger LOG = LogManager.getLogger(OgnlValueStack.class); - - private static final long serialVersionUID = 370737852934925530L; - - private static final String MAP_IDENTIFIER_KEY = "com.opensymphony.xwork2.util.OgnlValueStack.MAP_IDENTIFIER_KEY"; - - protected CompoundRoot root; - protected transient Map context; - protected Class defaultType; - protected Map overrides; - protected transient OgnlUtil ognlUtil; - protected transient SecurityMemberAccess securityMemberAccess; - - private transient XWorkConverter converter; - private boolean devMode; - private boolean logMissingProperties; - - protected OgnlValueStack(XWorkConverter xworkConverter, CompoundRootAccessor accessor, TextProvider prov, boolean allowStaticAccess) { - setRoot(xworkConverter, accessor, new CompoundRoot(), allowStaticAccess); - push(prov); - } - - protected OgnlValueStack(ValueStack vs, XWorkConverter xworkConverter, CompoundRootAccessor accessor, boolean allowStaticAccess) { - setRoot(xworkConverter, accessor, new CompoundRoot(vs.getRoot()), allowStaticAccess); - } - - @Inject - public void setOgnlUtil(OgnlUtil ognlUtil) { - this.ognlUtil = ognlUtil; - securityMemberAccess.setExcludedClasses(ognlUtil.getExcludedClasses()); - securityMemberAccess.setExcludedPackageNamePatterns(ognlUtil.getExcludedPackageNamePatterns()); - securityMemberAccess.setExcludedPackageNames(ognlUtil.getExcludedPackageNames()); - } - - protected void setRoot(XWorkConverter xworkConverter, CompoundRootAccessor accessor, CompoundRoot compoundRoot, - boolean allowStaticMethodAccess) { - this.root = compoundRoot; - this.securityMemberAccess = new SecurityMemberAccess(allowStaticMethodAccess); - this.context = Ognl.createDefaultContext(this.root, accessor, new OgnlTypeConverterWrapper(xworkConverter), securityMemberAccess); - context.put(VALUE_STACK, this); - Ognl.setClassResolver(context, accessor); - ((OgnlContext) context).setTraceEvaluations(false); - ((OgnlContext) context).setKeepLastEvaluation(false); - } - - @Inject(XWorkConstants.DEV_MODE) - public void setDevMode(String mode) { - this.devMode = BooleanUtils.toBoolean(mode); - } - - @Inject(value = "logMissingProperties", required = false) - public void setLogMissingProperties(String logMissingProperties) { - this.logMissingProperties = BooleanUtils.toBoolean(logMissingProperties); - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#getContext() - */ - public Map getContext() { - return context; - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#setDefaultType(java.lang.Class) - */ - public void setDefaultType(Class defaultType) { - this.defaultType = defaultType; - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#setExprOverrides(java.util.Map) - */ - public void setExprOverrides(Map overrides) { - if (this.overrides == null) { - this.overrides = overrides; - } else { - this.overrides.putAll(overrides); - } - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#getExprOverrides() - */ - public Map getExprOverrides() { - return this.overrides; - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#getRoot() - */ - public CompoundRoot getRoot() { - return root; - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#setParameter(String, Object) - */ - public void setParameter(String expr, Object value) { - setValue(expr, value, devMode); - } - - /** - - /** - * @see com.opensymphony.xwork2.util.ValueStack#setValue(java.lang.String, java.lang.Object) - */ - public void setValue(String expr, Object value) { - setValue(expr, value, devMode); - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#setValue(java.lang.String, java.lang.Object, boolean) - */ - public void setValue(String expr, Object value, boolean throwExceptionOnFailure) { - Map context = getContext(); - try { - trySetValue(expr, value, throwExceptionOnFailure, context); - } catch (OgnlException e) { - handleOgnlException(expr, value, throwExceptionOnFailure, e); - } catch (RuntimeException re) { //XW-281 - handleRuntimeException(expr, value, throwExceptionOnFailure, re); - } finally { - cleanUpContext(context); - } - } - - private void trySetValue(String expr, Object value, boolean throwExceptionOnFailure, Map context) throws OgnlException { - context.put(XWorkConverter.CONVERSION_PROPERTY_FULLNAME, expr); - context.put(REPORT_ERRORS_ON_NO_PROP, (throwExceptionOnFailure) ? Boolean.TRUE : Boolean.FALSE); - ognlUtil.setValue(expr, context, root, value); - } - - private void cleanUpContext(Map context) { - ReflectionContextState.clear(context); - context.remove(XWorkConverter.CONVERSION_PROPERTY_FULLNAME); - context.remove(REPORT_ERRORS_ON_NO_PROP); - } - - protected void handleRuntimeException(String expr, Object value, boolean throwExceptionOnFailure, RuntimeException re) { - if (throwExceptionOnFailure) { - String message = ErrorMessageBuilder.create() - .errorSettingExpressionWithValue(expr, value) - .build(); - throw new XWorkException(message, re); - } else { - LOG.warn("Error setting value [{}] with expression [{}]", value, expr, re); - } - } - - protected void handleOgnlException(String expr, Object value, boolean throwExceptionOnFailure, OgnlException e) { - boolean shouldLog = shouldLogMissingPropertyWarning(e); - String msg = null; - if (throwExceptionOnFailure || shouldLog) { - msg = ErrorMessageBuilder.create().errorSettingExpressionWithValue(expr, value).build(); - } - if (shouldLog) { - LOG.warn(msg, e); - } - - if (throwExceptionOnFailure) { - throw new XWorkException(msg, e); - } - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#findString(java.lang.String) - */ - public String findString(String expr) { - return (String) findValue(expr, String.class); - } - - public String findString(String expr, boolean throwExceptionOnFailure) { - return (String) findValue(expr, String.class, throwExceptionOnFailure); - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#findValue(java.lang.String) - */ - public Object findValue(String expr, boolean throwExceptionOnFailure) { - try { - setupExceptionOnFailure(throwExceptionOnFailure); - return tryFindValueWhenExpressionIsNotNull(expr); - } catch (OgnlException e) { - return handleOgnlException(expr, throwExceptionOnFailure, e); - } catch (Exception e) { - return handleOtherException(expr, throwExceptionOnFailure, e); - } finally { - ReflectionContextState.clear(context); - } - } - - protected void setupExceptionOnFailure(boolean throwExceptionOnFailure) { - if (throwExceptionOnFailure) { - context.put(THROW_EXCEPTION_ON_FAILURE, true); - } - } - - private Object tryFindValueWhenExpressionIsNotNull(String expr) throws OgnlException { - if (expr == null) { - return null; - } - return tryFindValue(expr); - } - - protected Object handleOtherException(String expr, boolean throwExceptionOnFailure, Exception e) { - logLookupFailure(expr, e); - - if (throwExceptionOnFailure) - throw new XWorkException(e); - - return findInContext(expr); - } - - private Object tryFindValue(String expr) throws OgnlException { - Object value; - expr = lookupForOverrides(expr); - if (defaultType != null) { - value = findValue(expr, defaultType); - } else { - value = getValueUsingOgnl(expr); - if (value == null) { - value = findInContext(expr); - } - } - return value; - } - - private String lookupForOverrides(String expr) { - if ((overrides != null) && overrides.containsKey(expr)) { - expr = (String) overrides.get(expr); - } - return expr; - } - - private Object getValueUsingOgnl(String expr) throws OgnlException { - try { - return ognlUtil.getValue(expr, context, root); - } finally { - context.remove(THROW_EXCEPTION_ON_FAILURE); - } - } - - public Object findValue(String expr) { - return findValue(expr, false); - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#findValue(java.lang.String, java.lang.Class) - */ - public Object findValue(String expr, Class asType, boolean throwExceptionOnFailure) { - try { - setupExceptionOnFailure(throwExceptionOnFailure); - return tryFindValueWhenExpressionIsNotNull(expr, asType); - } catch (OgnlException e) { - final Object value = handleOgnlException(expr, throwExceptionOnFailure, e); - return converter.convertValue(getContext(), value, asType); - } catch (Exception e) { - final Object value = handleOtherException(expr, throwExceptionOnFailure, e); - return converter.convertValue(getContext(), value, asType); - } finally { - ReflectionContextState.clear(context); - } - } - - private Object tryFindValueWhenExpressionIsNotNull(String expr, Class asType) throws OgnlException { - if (expr == null) { - return null; - } - return tryFindValue(expr, asType); - } - - protected Object handleOgnlException(String expr, boolean throwExceptionOnFailure, OgnlException e) { - Object ret = findInContext(expr); - if (ret == null) { - if (shouldLogMissingPropertyWarning(e)) { - LOG.warn("Could not find property [{}]!", expr, e); - } - if (throwExceptionOnFailure) { - throw new XWorkException(e); - } - } - return ret; - } - - protected boolean shouldLogMissingPropertyWarning(OgnlException e) { - return (e instanceof NoSuchPropertyException || e instanceof MethodFailedException) - && devMode && logMissingProperties; - } - - private Object tryFindValue(String expr, Class asType) throws OgnlException { - Object value = null; - try { - expr = lookupForOverrides(expr); - value = getValue(expr, asType); - if (value == null) { - value = findInContext(expr); - return converter.convertValue(getContext(), value, asType); - } - } finally { - context.remove(THROW_EXCEPTION_ON_FAILURE); - } - return value; - } - - private Object getValue(String expr, Class asType) throws OgnlException { - return ognlUtil.getValue(expr, context, root, asType); - } - - protected Object findInContext(String name) { - return getContext().get(name); - } - - public Object findValue(String expr, Class asType) { - return findValue(expr, asType, false); - } - - /** - * Log a failed lookup, being more verbose when devMode=true. - * - * @param expr The failed expression - * @param e The thrown exception. - */ - private void logLookupFailure(String expr, Exception e) { - if (devMode && LOG.isWarnEnabled()) { - LOG.warn("Caught an exception while evaluating expression '{}' against value stack", expr, e); - LOG.warn("NOTE: Previous warning message was issued due to devMode set to true."); - } else { - LOG.debug("Caught an exception while evaluating expression '{}' against value stack", expr, e); - } - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#peek() - */ - public Object peek() { - return root.peek(); - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#pop() - */ - public Object pop() { - return root.pop(); - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#push(java.lang.Object) - */ - public void push(Object o) { - root.push(o); - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#set(java.lang.String, java.lang.Object) - */ - public void set(String key, Object o) { - //set basically is backed by a Map pushed on the stack with a key being put on the map and the Object being the value - Map setMap = retrieveSetMap(); - setMap.put(key, o); - } - - private Map retrieveSetMap() { - Map setMap; - Object topObj = peek(); - if (shouldUseOldMap(topObj)) { - setMap = (Map) topObj; - } else { - setMap = new HashMap(); - setMap.put(MAP_IDENTIFIER_KEY, ""); - push(setMap); - } - return setMap; - } - - /** - * check if this is a Map put on the stack for setting if so just use the old map (reduces waste) - */ - private boolean shouldUseOldMap(Object topObj) { - return topObj instanceof Map && ((Map) topObj).get(MAP_IDENTIFIER_KEY) != null; - } - - /** - * @see com.opensymphony.xwork2.util.ValueStack#size() - */ - public int size() { - return root.size(); - } - - private Object readResolve() { - // TODO: this should be done better - ActionContext ac = ActionContext.getContext(); - Container cont = ac.getContainer(); - XWorkConverter xworkConverter = cont.getInstance(XWorkConverter.class); - CompoundRootAccessor accessor = (CompoundRootAccessor) cont.getInstance(PropertyAccessor.class, CompoundRoot.class.getName()); - TextProvider prov = cont.getInstance(TextProvider.class, "system"); - boolean allow = BooleanUtils.toBoolean(cont.getInstance(String.class, XWorkConstants.ALLOW_STATIC_METHOD_ACCESS)); - OgnlValueStack aStack = new OgnlValueStack(xworkConverter, accessor, prov, allow); - aStack.setOgnlUtil(cont.getInstance(OgnlUtil.class)); - aStack.setRoot(xworkConverter, accessor, this.root, allow); - - return aStack; - } - - - public void clearContextValues() { - //this is an OGNL ValueStack so the context will be an OgnlContext - //it would be better to make context of type OgnlContext - ((OgnlContext) context).getValues().clear(); - } - - public void setAcceptProperties(Set acceptedProperties) { - securityMemberAccess.setAcceptProperties(acceptedProperties); - } - - public void setExcludeProperties(Set excludeProperties) { - securityMemberAccess.setExcludeProperties(excludeProperties); - } - - @Inject - public void setXWorkConverter(final XWorkConverter converter) { - this.converter = converter; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStackFactory.java b/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStackFactory.java deleted file mode 100644 index 674d7e2e5d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/OgnlValueStackFactory.java +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.TextProvider; -import com.opensymphony.xwork2.conversion.NullHandler; -import com.opensymphony.xwork2.conversion.impl.XWorkConverter; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.ognl.accessor.CompoundRootAccessor; -import com.opensymphony.xwork2.util.CompoundRoot; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.util.ValueStackFactory; -import ognl.MethodAccessor; -import ognl.OgnlRuntime; -import ognl.PropertyAccessor; -import org.apache.commons.lang3.BooleanUtils; - -import java.util.Map; -import java.util.Set; - -/** - * Creates an Ognl value stack - */ -public class OgnlValueStackFactory implements ValueStackFactory { - - protected XWorkConverter xworkConverter; - protected CompoundRootAccessor compoundRootAccessor; - protected TextProvider textProvider; - protected Container container; - protected boolean allowStaticMethodAccess; - - @Inject - public void setXWorkConverter(XWorkConverter converter) { - this.xworkConverter = converter; - } - - @Inject("system") - public void setTextProvider(TextProvider textProvider) { - this.textProvider = textProvider; - } - - @Inject(value="allowStaticMethodAccess", required=false) - public void setAllowStaticMethodAccess(String allowStaticMethodAccess) { - this.allowStaticMethodAccess = BooleanUtils.toBoolean(allowStaticMethodAccess); - } - - public ValueStack createValueStack() { - ValueStack stack = new OgnlValueStack(xworkConverter, compoundRootAccessor, textProvider, allowStaticMethodAccess); - container.inject(stack); - stack.getContext().put(ActionContext.CONTAINER, container); - return stack; - } - - public ValueStack createValueStack(ValueStack stack) { - ValueStack result = new OgnlValueStack(stack, xworkConverter, compoundRootAccessor, allowStaticMethodAccess); - container.inject(result); - stack.getContext().put(ActionContext.CONTAINER, container); - return result; - } - - @Inject - public void setContainer(Container container) throws ClassNotFoundException { - Set names = container.getInstanceNames(PropertyAccessor.class); - for (String name : names) { - Class cls = Class.forName(name); - if (cls != null) { - if (Map.class.isAssignableFrom(cls)) { - PropertyAccessor acc = container.getInstance(PropertyAccessor.class, name); - } - OgnlRuntime.setPropertyAccessor(cls, container.getInstance(PropertyAccessor.class, name)); - if (compoundRootAccessor == null && CompoundRoot.class.isAssignableFrom(cls)) { - compoundRootAccessor = (CompoundRootAccessor) container.getInstance(PropertyAccessor.class, name); - } - } - } - - names = container.getInstanceNames(MethodAccessor.class); - for (String name : names) { - Class cls = Class.forName(name); - if (cls != null) { - OgnlRuntime.setMethodAccessor(cls, container.getInstance(MethodAccessor.class, name)); - } - } - - names = container.getInstanceNames(NullHandler.class); - for (String name : names) { - Class cls = Class.forName(name); - if (cls != null) { - OgnlRuntime.setNullHandler(cls, new OgnlNullHandlerWrapper(container.getInstance(NullHandler.class, name))); - } - } - if (compoundRootAccessor == null) { - throw new IllegalStateException("Couldn't find the compound root accessor"); - } - this.container = container; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java b/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java deleted file mode 100644 index 530be65215..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/SecurityMemberAccess.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl; - -import ognl.DefaultMemberAccess; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.lang.reflect.Member; -import java.lang.reflect.Modifier; -import java.util.Collections; -import java.util.Map; -import java.util.Set; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Allows access decisions to be made on the basis of whether a member is static or not. - * Also blocks or allows access to properties. - */ -public class SecurityMemberAccess extends DefaultMemberAccess { - - private static final Logger LOG = LogManager.getLogger(SecurityMemberAccess.class); - - private final boolean allowStaticMethodAccess; - private Set excludeProperties = Collections.emptySet(); - private Set acceptProperties = Collections.emptySet(); - private Set> excludedClasses = Collections.emptySet(); - private Set excludedPackageNamePatterns = Collections.emptySet(); - private Set excludedPackageNames = Collections.emptySet(); - - public SecurityMemberAccess(boolean method) { - super(false); - allowStaticMethodAccess = method; - } - - public boolean getAllowStaticMethodAccess() { - return allowStaticMethodAccess; - } - - @Override - public boolean isAccessible(Map context, Object target, Member member, String propertyName) { - LOG.debug("Checking access for [target: {}, member: {}, property: {}] is deprecated!", target, member, propertyName); - - if (checkEnumAccess(target, member)) { - LOG.trace("Allowing access to enum: {}", target); - return true; - } - - Class targetClass = target.getClass(); - Class memberClass = member.getDeclaringClass(); - - if (Modifier.isStatic(member.getModifiers()) && allowStaticMethodAccess) { - LOG.debug("Support for accessing static methods [target: {}, member: {}, property: {}] is deprecated!", target, member, propertyName); - if (!isClassExcluded(member.getDeclaringClass())) { - targetClass = member.getDeclaringClass(); - } - } - - if (isPackageExcluded(targetClass.getPackage(), memberClass.getPackage())) { - LOG.warn("Package of target [{}] or package of member [{}] are excluded!", target, member); - return false; - } - - if (isClassExcluded(targetClass)) { - LOG.warn("Target class [{}] is excluded!", target); - return false; - } - - if (isClassExcluded(memberClass)) { - LOG.warn("Declaring class of member type [{}] is excluded!", member); - return false; - } - - boolean allow = true; - if (!checkStaticMethodAccess(member)) { - LOG.warn("Access to static [{}] is blocked!", member); - allow = false; - } - - //failed static test - if (!allow) { - return false; - } - - // Now check for standard scope rules - return super.isAccessible(context, target, member, propertyName) && isAcceptableProperty(propertyName); - } - - protected boolean checkStaticMethodAccess(Member member) { - int modifiers = member.getModifiers(); - if (Modifier.isStatic(modifiers)) { - return allowStaticMethodAccess; - } else { - return true; - } - } - - protected boolean checkEnumAccess(Object target, Member member) { - if (target instanceof Class) { - Class clazz = (Class) target; - if (Enum.class.isAssignableFrom(clazz) && member.getName().equals("values")) { - return true; - } - } - return false; - } - - protected boolean isPackageExcluded(Package targetPackage, Package memberPackage) { - if (targetPackage == null || memberPackage == null) { - LOG.warn("The use of the default (unnamed) package is discouraged!"); - } - - final String targetPackageName = targetPackage == null ? "" : targetPackage.getName(); - final String memberPackageName = memberPackage == null ? "" : memberPackage.getName(); - - for (Pattern pattern : excludedPackageNamePatterns) { - if (pattern.matcher(targetPackageName).matches() || pattern.matcher(memberPackageName).matches()) { - return true; - } - } - - for (String packageName: excludedPackageNames) { - if (targetPackageName.startsWith(packageName) || targetPackageName.equals(packageName) - || memberPackageName.startsWith(packageName) || memberPackageName.equals(packageName)) { - return true; - } - } - - return false; - } - - protected boolean isClassExcluded(Class clazz) { - if (clazz == Object.class || (clazz == Class.class && !allowStaticMethodAccess)) { - return true; - } - for (Class excludedClass : excludedClasses) { - if (clazz.isAssignableFrom(excludedClass)) { - return true; - } - } - return false; - } - - protected boolean isAcceptableProperty(String name) { - return name == null || ((!isExcluded(name)) && isAccepted(name)); - } - - protected boolean isAccepted(String paramName) { - if (!this.acceptProperties.isEmpty()) { - for (Pattern pattern : acceptProperties) { - Matcher matcher = pattern.matcher(paramName); - if (matcher.matches()) { - return true; - } - } - - //no match, but acceptedParams is not empty - return false; - } - - //empty acceptedParams - return true; - } - - protected boolean isExcluded(String paramName) { - if (!this.excludeProperties.isEmpty()) { - for (Pattern pattern : excludeProperties) { - Matcher matcher = pattern.matcher(paramName); - if (matcher.matches()) { - return true; - } - } - } - return false; - } - - public void setExcludeProperties(Set excludeProperties) { - this.excludeProperties = excludeProperties; - } - - public void setAcceptProperties(Set acceptedProperties) { - this.acceptProperties = acceptedProperties; - } - - public void setExcludedClasses(Set> excludedClasses) { - this.excludedClasses = excludedClasses; - } - - public void setExcludedPackageNamePatterns(Set excludedPackageNamePatterns) { - this.excludedPackageNamePatterns = excludedPackageNamePatterns; - } - - public void setExcludedPackageNames(Set excludedPackageNames) { - this.excludedPackageNames = excludedPackageNames; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/XWorkTypeConverterWrapper.java b/core/src/main/java/com/opensymphony/xwork2/ognl/XWorkTypeConverterWrapper.java deleted file mode 100644 index dbf21f67be..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/XWorkTypeConverterWrapper.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl; - -import com.opensymphony.xwork2.conversion.TypeConverter; - -import java.lang.reflect.Member; -import java.util.Map; - -/** - * Wraps an OGNL TypeConverter as an XWork TypeConverter - */ -public class XWorkTypeConverterWrapper implements TypeConverter { - - private ognl.TypeConverter typeConverter; - - public XWorkTypeConverterWrapper(ognl.TypeConverter conv) { - this.typeConverter = conv; - } - - public Object convertValue(Map context, Object target, Member member, - String propertyName, Object value, Class toType) { - return typeConverter.convertValue(context, target, member, propertyName, value, toType); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/CompoundRootAccessor.java b/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/CompoundRootAccessor.java deleted file mode 100644 index 3beb14a0db..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/CompoundRootAccessor.java +++ /dev/null @@ -1,327 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl.accessor; - -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.XWorkException; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.ognl.OgnlValueStack; -import com.opensymphony.xwork2.util.CompoundRoot; -import com.opensymphony.xwork2.util.ValueStack; -import ognl.*; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.beans.IntrospectionException; -import java.beans.PropertyDescriptor; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; - -import static java.lang.String.format; -import static org.apache.commons.lang3.BooleanUtils.toBoolean; - -/** - * A stack that is able to call methods on objects in the stack. - * - * @author $Author$ - * @author Rainer Hermanns - * @version $Revision$ - */ -public class CompoundRootAccessor implements PropertyAccessor, MethodAccessor, ClassResolver { - - /** - * Used by OGNl to generate bytecode - */ - public String getSourceAccessor(OgnlContext context, Object target, Object index) { - return null; - } - - /** - * Used by OGNl to generate bytecode - */ - public String getSourceSetter(OgnlContext context, Object target, Object index) { - return null; - } - - private final static Logger LOG = LogManager.getLogger(CompoundRootAccessor.class); - private final static Class[] EMPTY_CLASS_ARRAY = new Class[0]; - private static Map invalidMethods = new ConcurrentHashMap<>(); - private boolean devMode = false; - - @Inject(XWorkConstants.DEV_MODE) - public void setDevMode(String mode) { - this.devMode = BooleanUtils.toBoolean(mode); - } - - public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { - CompoundRoot root = (CompoundRoot) target; - OgnlContext ognlContext = (OgnlContext) context; - - for (Object o : root) { - if (o == null) { - continue; - } - - try { - if (OgnlRuntime.hasSetProperty(ognlContext, o, name)) { - OgnlRuntime.setProperty(ognlContext, o, name, value); - - return; - } else if (o instanceof Map) { - @SuppressWarnings("unchecked") - Map map = (Map) o; - try { - map.put(name, value); - return; - } catch (UnsupportedOperationException e) { - // This is an unmodifiable Map, so move on to the next element in the stack - } - } -// } catch (OgnlException e) { -// if (e.getReason() != null) { -// final String msg = "Caught an Ognl exception while setting property " + name; -// log.error(msg, e); -// throw new RuntimeException(msg, e.getReason()); -// } - } catch (IntrospectionException e) { - // this is OK if this happens, we'll just keep trying the next - } - } - - boolean reportError = toBoolean((Boolean) context.get(ValueStack.REPORT_ERRORS_ON_NO_PROP)); - - if (reportError || devMode) { - final String msg = format("No object in the CompoundRoot has a publicly accessible property named '%s' " + - "(no setter could be found).", name); - if (reportError) { - throw new XWorkException(msg); - } else { - LOG.warn(msg); - } - } - } - - public Object getProperty(Map context, Object target, Object name) throws OgnlException { - CompoundRoot root = (CompoundRoot) target; - OgnlContext ognlContext = (OgnlContext) context; - - if (name instanceof Integer) { - Integer index = (Integer) name; - return root.cutStack(index); - } else if (name instanceof String) { - if ("top".equals(name)) { - if (root.size() > 0) { - return root.get(0); - } else { - return null; - } - } - - for (Object o : root) { - if (o == null) { - continue; - } - - try { - if ((OgnlRuntime.hasGetProperty(ognlContext, o, name)) || ((o instanceof Map) && ((Map) o).containsKey(name))) { - return OgnlRuntime.getProperty(ognlContext, o, name); - } - } catch (OgnlException e) { - if (e.getReason() != null) { - final String msg = "Caught an Ognl exception while getting property " + name; - throw new XWorkException(msg, e); - } - } catch (IntrospectionException e) { - // this is OK if this happens, we'll just keep trying the next - } - } - - //property was not found - if (context.containsKey(OgnlValueStack.THROW_EXCEPTION_ON_FAILURE)) - throw new NoSuchPropertyException(target, name); - else - return null; - } else { - return null; - } - } - - public Object callMethod(Map context, Object target, String name, Object[] objects) throws MethodFailedException { - CompoundRoot root = (CompoundRoot) target; - - if ("describe".equals(name)) { - Object v; - if (objects != null && objects.length == 1) { - v = objects[0]; - } else { - v = root.get(0); - } - - - if (v instanceof Collection || v instanceof Map || v.getClass().isArray()) { - return v.toString(); - } - - try { - Map descriptors = OgnlRuntime.getPropertyDescriptors(v.getClass()); - - int maxSize = 0; - for (String pdName : descriptors.keySet()) { - if (pdName.length() > maxSize) { - maxSize = pdName.length(); - } - } - - SortedSet set = new TreeSet<>(); - StringBuffer sb = new StringBuffer(); - for (PropertyDescriptor pd : descriptors.values()) { - - sb.append(pd.getName()).append(": "); - int padding = maxSize - pd.getName().length(); - for (int i = 0; i < padding; i++) { - sb.append(" "); - } - sb.append(pd.getPropertyType().getName()); - set.add(sb.toString()); - - sb = new StringBuffer(); - } - - sb = new StringBuffer(); - for (Object aSet : set) { - String s = (String) aSet; - sb.append(s).append("\n"); - } - - return sb.toString(); - } catch (IntrospectionException | OgnlException e) { - LOG.debug("Got exception in callMethod", e); - } - return null; - } - - for (Object o : root) { - if (o == null) { - continue; - } - - Class clazz = o.getClass(); - Class[] argTypes = getArgTypes(objects); - - MethodCall mc = null; - - if (argTypes != null) { - mc = new MethodCall(clazz, name, argTypes); - } - - if ((argTypes == null) || !invalidMethods.containsKey(mc)) { - try { - Object value = OgnlRuntime.callMethod((OgnlContext) context, o, name, objects); - - if (value != null) { - return value; - } - } catch (OgnlException e) { - // try the next one - Throwable reason = e.getReason(); - - if (!context.containsKey(OgnlValueStack.THROW_EXCEPTION_ON_FAILURE) && (mc != null) && (reason != null) && (reason.getClass() == NoSuchMethodException.class)) { - invalidMethods.put(mc, Boolean.TRUE); - } else if (reason != null) { - throw new MethodFailedException(o, name, e.getReason()); - } - } - } - } - - return null; - } - - public Object callStaticMethod(Map transientVars, Class aClass, String s, Object[] objects) throws MethodFailedException { - return null; - } - - public Class classForName(String className, Map context) throws ClassNotFoundException { - Object root = Ognl.getRoot(context); - - try { - if (root instanceof CompoundRoot) { - if (className.startsWith("vs")) { - CompoundRoot compoundRoot = (CompoundRoot) root; - - if ("vs".equals(className)) { - return compoundRoot.peek().getClass(); - } - - int index = Integer.parseInt(className.substring(2)); - - return compoundRoot.get(index - 1).getClass(); - } - } - } catch (Exception e) { - LOG.debug("Got exception when tried to get class for name [{}]", className, e); - } - - return Thread.currentThread().getContextClassLoader().loadClass(className); - } - - private Class[] getArgTypes(Object[] args) { - if (args == null) { - return EMPTY_CLASS_ARRAY; - } - - Class[] classes = new Class[args.length]; - - for (int i = 0; i < args.length; i++) { - Object arg = args[i]; - classes[i] = (arg != null) ? arg.getClass() : Object.class; - } - - return classes; - } - - - static class MethodCall { - Class clazz; - String name; - Class[] args; - int hash; - - public MethodCall(Class clazz, String name, Class[] args) { - this.clazz = clazz; - this.name = name; - this.args = args; - this.hash = clazz.hashCode() + name.hashCode(); - - for (Class arg : args) { - hash += arg.hashCode(); - } - } - - @Override - public boolean equals(Object obj) { - MethodCall mc = (CompoundRootAccessor.MethodCall) obj; - - return (mc.clazz.equals(clazz) && mc.name.equals(name) && Arrays.equals(mc.args, args)); - } - - @Override - public int hashCode() { - return hash; - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/HttpParametersPropertyAccessor.java b/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/HttpParametersPropertyAccessor.java deleted file mode 100644 index 589d914712..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/HttpParametersPropertyAccessor.java +++ /dev/null @@ -1,25 +0,0 @@ -/** - * - */ -package com.opensymphony.xwork2.ognl.accessor; - -import ognl.ObjectPropertyAccessor; -import ognl.OgnlException; -import org.apache.struts2.dispatcher.HttpParameters; -import org.apache.struts2.dispatcher.Parameter; - -import java.util.Map; - -public class HttpParametersPropertyAccessor extends ObjectPropertyAccessor { - - @Override - public Object getProperty(Map context, Object target, Object oname) throws OgnlException { - HttpParameters parameters = (HttpParameters) target; - return parameters.get(String.valueOf(oname)).getObject(); - } - - @Override - public void setProperty(Map context, Object target, Object oname, Object value) throws OgnlException { - throw new OgnlException("Access to " + target.getClass().getName() + " is read-only!"); - } -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/ObjectAccessor.java b/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/ObjectAccessor.java deleted file mode 100644 index 255a0fce6f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/ObjectAccessor.java +++ /dev/null @@ -1,29 +0,0 @@ -/** - * - */ -package com.opensymphony.xwork2.ognl.accessor; - -import com.opensymphony.xwork2.conversion.impl.XWorkConverter; -import com.opensymphony.xwork2.ognl.OgnlValueStack; -import com.opensymphony.xwork2.util.reflection.ReflectionContextState; -import ognl.ObjectPropertyAccessor; -import ognl.OgnlException; - -import java.util.Map; - -public class ObjectAccessor extends ObjectPropertyAccessor { - @Override - public Object getProperty(Map map, Object o, Object o1) throws OgnlException { - Object obj = super.getProperty(map, o, o1); - - map.put(XWorkConverter.LAST_BEAN_CLASS_ACCESSED, o.getClass()); - map.put(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED, o1.toString()); - ReflectionContextState.updateCurrentPropertyPath(map, o1); - return obj; - } - - @Override - public void setProperty(Map map, Object o, Object o1, Object o2) throws OgnlException { - super.setProperty(map, o, o1, o2); - } -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/ObjectProxyPropertyAccessor.java b/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/ObjectProxyPropertyAccessor.java deleted file mode 100644 index f9f12719ca..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/ObjectProxyPropertyAccessor.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.ognl.accessor; - -import com.opensymphony.xwork2.ognl.ObjectProxy; -import com.opensymphony.xwork2.util.reflection.ReflectionContextState; -import ognl.OgnlException; -import ognl.OgnlRuntime; -import ognl.PropertyAccessor; -import ognl.OgnlContext; - -import java.util.Map; - -/** - * Is able to access (set/get) properties on a given object. - *

    - * Uses Ognl internal. - *

    - * - * @author Gabe - */ -public class ObjectProxyPropertyAccessor implements PropertyAccessor { - - /** - * Used by OGNl to generate bytecode - */ - public String getSourceAccessor(OgnlContext context, Object target, Object index) { - return null; //To change body of implemented methods use File | Settings | File Templates. - } - - /** - * Used by OGNl to generate bytecode - */ - public String getSourceSetter(OgnlContext context, Object target, Object index) { - return null; - } - - public Object getProperty(Map context, Object target, Object name) throws OgnlException { - ObjectProxy proxy = (ObjectProxy) target; - setupContext(context, proxy); - - return OgnlRuntime.getPropertyAccessor(proxy.getValue().getClass()).getProperty(context, target, name); - - } - - public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { - ObjectProxy proxy = (ObjectProxy) target; - setupContext(context, proxy); - - OgnlRuntime.getPropertyAccessor(proxy.getValue().getClass()).setProperty(context, target, name, value); - } - - /** - * Sets up the context with the last property and last class - * accessed. - * - * @param context - * @param proxy - */ - private void setupContext(Map context, ObjectProxy proxy) { - ReflectionContextState.setLastBeanClassAccessed(context, proxy.getLastClassAccessed()); - ReflectionContextState.setLastBeanPropertyAccessed(context, proxy.getLastPropertyAccessed()); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/ParameterPropertyAccessor.java b/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/ParameterPropertyAccessor.java deleted file mode 100644 index 48027df62c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/ParameterPropertyAccessor.java +++ /dev/null @@ -1,33 +0,0 @@ -/** - * - */ -package com.opensymphony.xwork2.ognl.accessor; - -import ognl.ObjectPropertyAccessor; -import ognl.OgnlException; -import org.apache.struts2.dispatcher.Parameter; - -import java.util.Map; - -public class ParameterPropertyAccessor extends ObjectPropertyAccessor { - - @Override - public Object getProperty(Map context, Object target, Object oname) throws OgnlException { - if (target instanceof Parameter) { - if ("value".equalsIgnoreCase(String.valueOf(oname))) { - throw new OgnlException("Access to " + oname + " is not allowed! Call parameter name directly!"); - } - return ((Parameter) target).getObject(); - } - return super.getProperty(context, target, oname); - } - - @Override - public void setProperty(Map context, Object target, Object oname, Object value) throws OgnlException { - if (target instanceof Parameter) { - throw new OgnlException("Access to " + target.getClass().getName() + " is read-only!"); - } else { - super.setProperty(context, target, oname, value); - } - } -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkEnumerationAccessor.java b/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkEnumerationAccessor.java deleted file mode 100644 index 84745e430a..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkEnumerationAccessor.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl.accessor; - -import ognl.EnumerationPropertyAccessor; -import ognl.ObjectPropertyAccessor; -import ognl.OgnlException; - -import java.util.Map; - - -/** - * @author plightbo - */ -public class XWorkEnumerationAccessor extends EnumerationPropertyAccessor { - - ObjectPropertyAccessor opa = new ObjectPropertyAccessor(); - - @Override - public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { - opa.setProperty(context, target, name, value); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkIteratorPropertyAccessor.java b/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkIteratorPropertyAccessor.java deleted file mode 100644 index 2a6184bc14..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkIteratorPropertyAccessor.java +++ /dev/null @@ -1,36 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl.accessor; - -import ognl.IteratorPropertyAccessor; -import ognl.ObjectPropertyAccessor; -import ognl.OgnlException; - -import java.util.Map; - - -/** - * @author plightbo - */ -public class XWorkIteratorPropertyAccessor extends IteratorPropertyAccessor { - - ObjectPropertyAccessor opa = new ObjectPropertyAccessor(); - - @Override - public void setProperty(Map context, Object target, Object name, Object value) throws OgnlException { - opa.setProperty(context, target, name, value); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkMapPropertyAccessorTest.java b/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkMapPropertyAccessorTest.java deleted file mode 100644 index a746c7e77d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkMapPropertyAccessorTest.java +++ /dev/null @@ -1,54 +0,0 @@ -package com.opensymphony.xwork2.ognl.accessor; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.XWorkTestCase; -import com.opensymphony.xwork2.util.Element; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.util.reflection.ReflectionContextState; - -import java.util.Collections; -import java.util.Map; - -public class XWorkMapPropertyAccessorTest extends XWorkTestCase { - public void testCreateNullObjectsIsFalseByDefault() { - ValueStack vs = ActionContext.getContext().getValueStack(); - vs.push(new MapHolder(Collections.emptyMap())); - assertNull(vs.findValue("map[key]")); - } - - public void testMapContentsAreReturned() { - ValueStack vs = ActionContext.getContext().getValueStack(); - vs.push(new MapHolder(Collections.singletonMap("key", "value"))); - assertEquals("value", vs.findValue("map['key']")); - } - - public void testNullIsNotReturnedWhenCreateNullObjectsIsSpecified() { - ValueStack vs = ActionContext.getContext().getValueStack(); - vs.push(new MapHolder(Collections.emptyMap())); - ReflectionContextState.setCreatingNullObjects(vs.getContext(), true); - - Object value = vs.findValue("map['key']"); - assertNotNull(value); - assertSame(Object.class, value.getClass()); - } - - public void testNullIsReturnedWhenCreateNullObjectsIsSpecifiedAsFalse() { - ValueStack vs = ActionContext.getContext().getValueStack(); - vs.push(new MapHolder(Collections.emptyMap())); - ReflectionContextState.setCreatingNullObjects(vs.getContext(), false); - assertNull(vs.findValue("map['key']")); - } - - private static class MapHolder { - private final Map map; - - public MapHolder(Map m) { - this.map = m; - } - - @Element(value = Object.class) - public Map getMap() { - return map; - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkMethodAccessor.java b/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkMethodAccessor.java deleted file mode 100644 index 74a34711ae..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkMethodAccessor.java +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl.accessor; - -import com.opensymphony.xwork2.util.reflection.ReflectionContextState; -import ognl.*; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.beans.PropertyDescriptor; -import java.util.Arrays; -import java.util.Collection; -import java.util.Map; - - -/** - * Allows methods to be executed under normal cirumstances, except when {@link ReflectionContextState#DENY_METHOD_EXECUTION} - * is in the action context with a value of true. - * - * @author Patrick Lightbody - * @author tmjee - */ -public class XWorkMethodAccessor extends ObjectMethodAccessor { - - private static final Logger LOG = LogManager.getLogger(XWorkMethodAccessor.class); - - @Override - public Object callMethod(Map context, Object object, String string, Object[] objects) throws MethodFailedException { - - //Collection property accessing - //this if statement ensures that ognl - //statements of the form someBean.mySet('keyPropVal') - //return the set element with value of the keyProp given - - if (objects.length == 1 && context instanceof OgnlContext) { - try { - OgnlContext ogContext=(OgnlContext)context; - if (OgnlRuntime.hasSetProperty(ogContext, object, string)) { - PropertyDescriptor descriptor=OgnlRuntime.getPropertyDescriptor(object.getClass(), string); - Class propertyType=descriptor.getPropertyType(); - if ((Collection.class).isAssignableFrom(propertyType)) { - //go directly through OgnlRuntime here - //so that property strings are not cleared - //i.e. OgnlUtil should be used initially, OgnlRuntime - //thereafter - - Object propVal=OgnlRuntime.getProperty(ogContext, object, string); - //use the Collection property accessor instead of the individual property accessor, because - //in the case of Lists otherwise the index property could be used - PropertyAccessor accessor=OgnlRuntime.getPropertyAccessor(Collection.class); - ReflectionContextState.setGettingByKeyProperty(ogContext,true); - return accessor.getProperty(ogContext,propVal,objects[0]); - } - } - } catch (Exception oe) { - //this exception should theoretically never happen - //log it - LOG.error("An unexpected exception occurred", oe); - } - - } - - //HACK - we pass indexed method access i.e. setXXX(A,B) pattern - if ((objects.length == 2 && string.startsWith("set")) || (objects.length == 1 && string.startsWith("get"))) { - Boolean exec = (Boolean) context.get(ReflectionContextState.DENY_INDEXED_ACCESS_EXECUTION); - boolean e = ((exec == null) ? false : exec.booleanValue()); - if (!e) { - return callMethodWithDebugInfo(context, object, string, objects); - } - } - Boolean exec = (Boolean) context.get(ReflectionContextState.DENY_METHOD_EXECUTION); - boolean e = ((exec == null) ? false : exec.booleanValue()); - - if (!e) { - return callMethodWithDebugInfo(context, object, string, objects); - } else { - return null; - } - } - - private Object callMethodWithDebugInfo(Map context, Object object, String methodName, Object[] objects) throws MethodFailedException { - try { - return super.callMethod(context, object, methodName, objects); - } - catch(MethodFailedException e) { - if (LOG.isDebugEnabled()) { - if (!(e.getReason() instanceof NoSuchMethodException)) { - // the method exists on the target object, but something went wrong - LOG.debug("Error calling method through OGNL: object: [{}] method: [{}] args: [{}]", e.getReason(), object.toString(), methodName, Arrays.toString(objects)); - } - } - throw e; - } - } - - @Override - public Object callStaticMethod(Map context, Class aClass, String string, Object[] objects) throws MethodFailedException { - Boolean exec = (Boolean) context.get(ReflectionContextState.DENY_METHOD_EXECUTION); - boolean e = ((exec == null) ? false : exec.booleanValue()); - - if (!e) { - return callStaticMethodWithDebugInfo(context, aClass, string, objects); - } else { - return null; - } - } - - private Object callStaticMethodWithDebugInfo(Map context, Class aClass, String methodName, - Object[] objects) throws MethodFailedException { - try { - return super.callStaticMethod(context, aClass, methodName, objects); - } - catch(MethodFailedException e) { - if (LOG.isDebugEnabled()) { - if (!(e.getReason() instanceof NoSuchMethodException)) { - // the method exists on the target class, but something went wrong - LOG.debug("Error calling method through OGNL, class: [{}] method: [{}] args: [{}]", e.getReason(), aClass.getName(), methodName, Arrays.toString(objects)); - } - } - throw e; - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkObjectPropertyAccessor.java b/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkObjectPropertyAccessor.java deleted file mode 100644 index 5351401bf7..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/ognl/accessor/XWorkObjectPropertyAccessor.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.ognl.accessor; - -import com.opensymphony.xwork2.conversion.impl.XWorkConverter; -import com.opensymphony.xwork2.util.reflection.ReflectionContextState; -import ognl.ObjectPropertyAccessor; -import ognl.OgnlException; - -import java.util.Map; - -/** - * @author Gabe - */ -public class XWorkObjectPropertyAccessor extends ObjectPropertyAccessor { - @Override - public Object getProperty(Map context, Object target, Object oname) - throws OgnlException { - //set the last set objects in the context - //so if the next objects accessed are - //Maps or Collections they can use the information - //to determine conversion types - context.put(XWorkConverter.LAST_BEAN_CLASS_ACCESSED, target.getClass()); - context.put(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED, oname.toString()); - ReflectionContextState.updateCurrentPropertyPath(context, oname); - return super.getProperty(context, target, oname); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/package.html b/core/src/main/java/com/opensymphony/xwork2/package.html deleted file mode 100644 index 3794154763..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/package.html +++ /dev/null @@ -1 +0,0 @@ -Main XWork interfaces and classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/result/ParamNameAwareResult.java b/core/src/main/java/com/opensymphony/xwork2/result/ParamNameAwareResult.java deleted file mode 100644 index 1067984c8e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/result/ParamNameAwareResult.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.opensymphony.xwork2.result; - -/** - * Accept parameter name/value to be set on {@link com.opensymphony.xwork2.Result} - */ -public interface ParamNameAwareResult { - - boolean acceptableParameterName(String name, String value); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/security/AcceptedPatternsChecker.java b/core/src/main/java/com/opensymphony/xwork2/security/AcceptedPatternsChecker.java deleted file mode 100644 index 64592fa643..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/security/AcceptedPatternsChecker.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.opensymphony.xwork2.security; - -import java.util.Set; -import java.util.regex.Pattern; - -/** - * Used across different interceptors to check if given string matches one of the excluded patterns. - */ -public interface AcceptedPatternsChecker { - - /** - * Checks if value matches any of patterns on exclude list - * - * @param value to check - * @return object containing result of matched pattern and pattern itself - */ - public IsAccepted isAccepted(String value); - - /** - * Sets excluded patterns during runtime - * - * @param commaDelimitedPatterns comma delimited string with patterns - */ - public void setAcceptedPatterns(String commaDelimitedPatterns); - - /** - * Set excluded patterns during runtime - * - * @param patterns array of additional excluded patterns - */ - public void setAcceptedPatterns(String[] patterns); - - /** - * Sets excluded patterns during runtime - * - * @param patterns set of additional patterns - */ - public void setAcceptedPatterns(Set patterns); - - /** - * Allow access list of all defined excluded patterns - * - * @return set of excluded patterns - */ - public Set getAcceptedPatterns(); - - public final static class IsAccepted { - - private final boolean accepted; - private final String acceptedPattern; - - public static IsAccepted yes(String acceptedPattern) { - return new IsAccepted(true, acceptedPattern); - } - - public static IsAccepted no(String acceptedPatterns) { - return new IsAccepted(false, acceptedPatterns); - } - - private IsAccepted(boolean accepted, String acceptedPattern) { - this.accepted = accepted; - this.acceptedPattern = acceptedPattern; - } - - public boolean isAccepted() { - return accepted; - } - - public String getAcceptedPattern() { - return acceptedPattern; - } - - @Override - public String toString() { - return "IsAccepted {" + - "accepted=" + accepted + - ", acceptedPattern=" + acceptedPattern + - " }"; - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsChecker.java b/core/src/main/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsChecker.java deleted file mode 100644 index 00e9f794c7..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/security/DefaultAcceptedPatternsChecker.java +++ /dev/null @@ -1,76 +0,0 @@ -package com.opensymphony.xwork2.security; - -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.TextParseUtil; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Pattern; - -public class DefaultAcceptedPatternsChecker implements AcceptedPatternsChecker { - - private static final Logger LOG = LogManager.getLogger(DefaultAcceptedPatternsChecker.class); - - public static final String[] ACCEPTED_PATTERNS = { - "\\w+((\\.\\w+)|(\\[\\d+\\])|(\\(\\d+\\))|(\\['(\\w|[\\u4e00-\\u9fa5])+'\\])|(\\('(\\w|[\\u4e00-\\u9fa5])+'\\)))*" - }; - - private Set acceptedPatterns; - - public DefaultAcceptedPatternsChecker() { - setAcceptedPatterns(ACCEPTED_PATTERNS); - } - - @Inject(value = XWorkConstants.OVERRIDE_ACCEPTED_PATTERNS, required = false) - public void setOverrideAcceptedPatterns(String acceptablePatterns) { - LOG.warn("Overriding accepted patterns [{}] with [{}], be aware that this affects all instances and safety of your application!", - XWorkConstants.OVERRIDE_ACCEPTED_PATTERNS, acceptablePatterns); - acceptedPatterns = new HashSet<>(); - for (String pattern : TextParseUtil.commaDelimitedStringToSet(acceptablePatterns)) { - acceptedPatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); - } - } - - @Inject(value = XWorkConstants.ADDITIONAL_ACCEPTED_PATTERNS, required = false) - public void setAdditionalAcceptedPatterns(String acceptablePatterns) { - LOG.warn("Adding additional global patterns [{}] to accepted patterns!", acceptablePatterns); - for (String pattern : TextParseUtil.commaDelimitedStringToSet(acceptablePatterns)) { - acceptedPatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); - } - } - - public void setAcceptedPatterns(String commaDelimitedPatterns) { - setAcceptedPatterns(TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns)); - } - - public void setAcceptedPatterns(String[] additionalPatterns) { - setAcceptedPatterns(new HashSet<>(Arrays.asList(additionalPatterns))); - } - - public void setAcceptedPatterns(Set patterns) { - LOG.trace("Sets accepted patterns [{}]", patterns); - acceptedPatterns = new HashSet<>(patterns.size()); - for (String pattern : patterns) { - acceptedPatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); - } - } - - public IsAccepted isAccepted(String value) { - for (Pattern acceptedPattern : acceptedPatterns) { - if (acceptedPattern.matcher(value).matches()) { - LOG.trace("[{}] matches accepted pattern [{}]", value, acceptedPattern); - return IsAccepted.yes(acceptedPattern.toString()); - } - } - return IsAccepted.no(acceptedPatterns.toString()); - } - - public Set getAcceptedPatterns() { - return acceptedPatterns; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsChecker.java b/core/src/main/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsChecker.java deleted file mode 100644 index 687d17f8d9..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/security/DefaultExcludedPatternsChecker.java +++ /dev/null @@ -1,87 +0,0 @@ -package com.opensymphony.xwork2.security; - -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.TextParseUtil; -import org.apache.commons.lang3.BooleanUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.struts2.StrutsConstants; - -import java.util.Arrays; -import java.util.HashSet; -import java.util.Set; -import java.util.regex.Pattern; - -public class DefaultExcludedPatternsChecker implements ExcludedPatternsChecker { - - private static final Logger LOG = LogManager.getLogger(DefaultExcludedPatternsChecker.class); - - public static final String[] EXCLUDED_PATTERNS = { - "(^|\\%\\{)((#?)(top(\\.|\\['|\\[\")|\\[\\d\\]\\.)?)(dojo|struts|session|request|response|application|servlet(Request|Response|Context)|parameters|context|_memberAccess)(\\.|\\[).*", - ".*(^|\\.|\\[|\\'|\"|get)class(\\(\\.|\\[|\\'|\").*" - }; - - private Set excludedPatterns; - - public DefaultExcludedPatternsChecker() { - setExcludedPatterns(EXCLUDED_PATTERNS); - } - - @Inject(value = XWorkConstants.OVERRIDE_EXCLUDED_PATTERNS, required = false) - public void setOverrideExcludePatterns(String excludePatterns) { - LOG.warn("Overriding excluded patterns [{}] with [{}], be aware that this affects all instances and safety of your application!", - XWorkConstants.OVERRIDE_EXCLUDED_PATTERNS, excludePatterns); - excludedPatterns = new HashSet(); - for (String pattern : TextParseUtil.commaDelimitedStringToSet(excludePatterns)) { - excludedPatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); - } - } - - @Inject(value = XWorkConstants.ADDITIONAL_EXCLUDED_PATTERNS, required = false) - public void setAdditionalExcludePatterns(String excludePatterns) { - LOG.debug("Adding additional global patterns [{}] to excluded patterns!", excludePatterns); - for (String pattern : TextParseUtil.commaDelimitedStringToSet(excludePatterns)) { - excludedPatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); - } - } - - @Inject(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION) - public void setDynamicMethodInvocation(String dmiValue) { - if (!BooleanUtils.toBoolean(dmiValue)) { - LOG.debug("DMI is disabled, adding DMI related excluded patterns"); - setAdditionalExcludePatterns("^(action|method):.*"); - } - } - - public void setExcludedPatterns(String commaDelimitedPatterns) { - setExcludedPatterns(TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns)); - } - - public void setExcludedPatterns(String[] patterns) { - setExcludedPatterns(new HashSet<>(Arrays.asList(patterns))); - } - - public void setExcludedPatterns(Set patterns) { - LOG.trace("Sets excluded patterns [{}]", patterns); - excludedPatterns = new HashSet<>(patterns.size()); - for (String pattern : patterns) { - excludedPatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE)); - } - } - - public IsExcluded isExcluded(String value) { - for (Pattern excludedPattern : excludedPatterns) { - if (excludedPattern.matcher(value).matches()) { - LOG.trace("[{}] matches excluded pattern [{}]", value, excludedPattern); - return IsExcluded.yes(excludedPattern); - } - } - return IsExcluded.no(excludedPatterns); - } - - public Set getExcludedPatterns() { - return excludedPatterns; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/security/ExcludedPatternsChecker.java b/core/src/main/java/com/opensymphony/xwork2/security/ExcludedPatternsChecker.java deleted file mode 100644 index 5a3bc0720a..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/security/ExcludedPatternsChecker.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.opensymphony.xwork2.security; - -import java.util.Set; -import java.util.regex.Pattern; - -/** - * Used across different interceptors to check if given string matches one of the excluded patterns. - */ -public interface ExcludedPatternsChecker { - - /** - * Checks if value matches any of patterns on exclude list - * - * @param value to check - * @return object containing result of matched pattern and pattern itself - */ - public IsExcluded isExcluded(String value); - - /** - * Sets excluded patterns during runtime - * - * @param commaDelimitedPatterns comma delimited string with patterns - */ - public void setExcludedPatterns(String commaDelimitedPatterns); - - /** - * Sets excluded patterns during runtime - * - * @param patterns array of additional excluded patterns - */ - public void setExcludedPatterns(String[] patterns); - - /** - * Sets excluded patterns during runtime - * - * @param patterns set of additional patterns - */ - public void setExcludedPatterns(Set patterns); - - /** - * Allow access list of all defined excluded patterns - * - * @return set of excluded patterns - */ - public Set getExcludedPatterns(); - - public final static class IsExcluded { - - private final boolean excluded; - private final String excludedPattern; - - public static IsExcluded yes(Pattern excludedPattern) { - return new IsExcluded(true, excludedPattern.pattern()); - } - - public static IsExcluded no(Set excludedPatterns) { - return new IsExcluded(false, excludedPatterns.toString()); - } - - private IsExcluded(boolean excluded, String excludedPattern) { - this.excluded = excluded; - this.excludedPattern = excludedPattern; - } - - public boolean isExcluded() { - return excluded; - } - - public String getExcludedPattern() { - return excludedPattern; - } - - @Override - public String toString() { - return "IsExcluded { " + - "excluded=" + excluded + - ", excludedPattern=" + excludedPattern + - " }"; - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/spring/interceptor/package.html b/core/src/main/java/com/opensymphony/xwork2/spring/interceptor/package.html deleted file mode 100644 index 6579e80e6b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/spring/interceptor/package.html +++ /dev/null @@ -1 +0,0 @@ -Spring specific interceptor classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/spring/package.html b/core/src/main/java/com/opensymphony/xwork2/spring/package.html deleted file mode 100644 index 91d2d95a5f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/spring/package.html +++ /dev/null @@ -1 +0,0 @@ -Spring ObjectFactory classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/test/StubConfigurationProvider.java b/core/src/main/java/com/opensymphony/xwork2/test/StubConfigurationProvider.java deleted file mode 100644 index 309db06230..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/test/StubConfigurationProvider.java +++ /dev/null @@ -1,36 +0,0 @@ -package com.opensymphony.xwork2.test; - -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.ConfigurationProvider; -import com.opensymphony.xwork2.inject.ContainerBuilder; -import com.opensymphony.xwork2.util.location.LocatableProperties; - -public class StubConfigurationProvider implements ConfigurationProvider { - - public void destroy() { - // TODO Auto-generated method stub - - } - - public void init(Configuration configuration) throws ConfigurationException { - // TODO Auto-generated method stub - } - - public void loadPackages() throws ConfigurationException { - // TODO Auto-generated method stub - - } - - public boolean needsReload() { - // TODO Auto-generated method stub - return false; - } - - public void register(ContainerBuilder builder, LocatableProperties props) - throws ConfigurationException { - // TODO Auto-generated method stub - - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java b/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java deleted file mode 100644 index 36166ddb22..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/AnnotationUtils.java +++ /dev/null @@ -1,286 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -import org.apache.commons.lang3.ArrayUtils; - -import java.lang.annotation.Annotation; -import java.lang.reflect.AnnotatedElement; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.Arrays; -import java.util.Collection; -import java.util.HashSet; -import java.util.List; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * AnnotationUtils - *

    - * Various utility methods dealing with annotations - *

    - * - * @author Rainer Hermanns - * @author Zsolt Szasz, zsolt at lorecraft dot com - * @author Dan Oxlade, dan d0t oxlade at gmail d0t c0m - * @version $Id$ - */ -public class AnnotationUtils { - - private static final Pattern SETTER_PATTERN = Pattern.compile("set([A-Z][A-Za-z0-9]*)$"); - private static final Pattern GETTER_PATTERN = Pattern.compile("(get|is|has)([A-Z][A-Za-z0-9]*)$"); - - /** - * Adds all fields with the specified Annotation of class clazz and its superclasses to allFields - * - * @param annotationClass the {@link Annotation}s to find - * @param clazz The {@link Class} to inspect - * @param allFields list of all fields - */ - public static void addAllFields(Class annotationClass, Class clazz, List allFields) { - - if (clazz == null) { - return; - } - - Field[] fields = clazz.getDeclaredFields(); - - for (Field field : fields) { - Annotation ann = field.getAnnotation(annotationClass); - if (ann != null) { - allFields.add(field); - } - } - addAllFields(annotationClass, clazz.getSuperclass(), allFields); - } - - /** - * Adds all methods with the specified Annotation of class clazz and its superclasses to allFields - * - * @param annotationClass the {@link Annotation}s to find - * @param clazz The {@link Class} to inspect - * @param allMethods list of all methods - */ - public static void addAllMethods(Class annotationClass, Class clazz, List allMethods) { - - if (clazz == null) { - return; - } - - Method[] methods = clazz.getDeclaredMethods(); - - for (Method method : methods) { - Annotation ann = method.getAnnotation(annotationClass); - if (ann != null) { - allMethods.add(method); - } - } - addAllMethods(annotationClass, clazz.getSuperclass(), allMethods); - } - - /** - * @param clazz The {@link Class} to inspect - * @param allInterfaces list of all interfaces - */ - public static void addAllInterfaces(Class clazz, List allInterfaces) { - if (clazz == null) { - return; - } - - Class[] interfaces = clazz.getInterfaces(); - allInterfaces.addAll(Arrays.asList(interfaces)); - addAllInterfaces(clazz.getSuperclass(), allInterfaces); - } - - /** - * For the given Class get a collection of the the {@link AnnotatedElement}s - * that match the given annotations or if no annotations are - * specified then return all of the annotated elements of the given Class. - * Includes only the method level annotations. - * - * @param clazz The {@link Class} to inspect - * @param annotation the {@link Annotation}s to find - * @return A {@link Collection}<{@link AnnotatedElement}> containing all of the - * method {@link AnnotatedElement}s matching the specified {@link Annotation}s - */ - public static Collection getAnnotatedMethods(Class clazz, Class... annotation) { - Collection toReturn = new HashSet<>(); - - for (Method m : clazz.getMethods()) { - boolean found = false; - for (Class c : annotation) { - if (null != findAnnotation(m, c)) { - found = true; - break; - } - } - if (found) { - toReturn.add(m); - } else if (ArrayUtils.isEmpty(annotation) && ArrayUtils.isNotEmpty(m.getAnnotations())) { - toReturn.add(m); - } - } - - return toReturn; - } - - /** - * Find a single {@link Annotation} of {@code annotationType} from the supplied - * {@link Method}, traversing its super methods (i.e., from superclasses and - * interfaces) if no annotation can be found on the given method itself. - *

    Annotations on methods are not inherited by default, so we need to handle - * this explicitly. - * - * @param method the method to look for annotations on - * @param annotationType the annotation type to look for - * @return the annotation found, or {@code null} if none - */ - public static A findAnnotation(Method method, Class annotationType) { - A result = getAnnotation(method, annotationType); - Class clazz = method.getDeclaringClass(); - if (result == null) { - result = searchOnInterfaces(method, annotationType, clazz.getInterfaces()); - } - while (result == null) { - clazz = clazz.getSuperclass(); - if (clazz == null || clazz.equals(Object.class)) { - break; - } - try { - Method equivalentMethod = clazz.getDeclaredMethod(method.getName(), method.getParameterTypes()); - result = getAnnotation(equivalentMethod, annotationType); - } catch (NoSuchMethodException ex) { - // No equivalent method found - } - if (result == null) { - result = searchOnInterfaces(method, annotationType, clazz.getInterfaces()); - } - } - return result; - } - - /** - * Get a single {@link Annotation} of {@code annotationType} from the supplied - * Method, Constructor or Field. Meta-annotations will be searched if the annotation - * is not declared locally on the supplied element. - * - * @param annotatedElement the Method, Constructor or Field from which to get the annotation - * @param annotationType the annotation type to look for, both locally and as a meta-annotation - * @return the matching annotation, or {@code null} if none found - */ - public static T getAnnotation(AnnotatedElement annotatedElement, Class annotationType) { - try { - T ann = annotatedElement.getAnnotation(annotationType); - if (ann == null) { - for (Annotation metaAnn : annotatedElement.getAnnotations()) { - ann = metaAnn.annotationType().getAnnotation(annotationType); - if (ann != null) { - break; - } - } - } - return ann; - } catch (Exception ex) { - // Assuming nested Class values not resolvable within annotation attributes... - return null; - } - } - - private static A searchOnInterfaces(Method method, Class annotationType, Class... ifcs) { - A annotation = null; - for (Class iface : ifcs) { - if (isInterfaceWithAnnotatedMethods(iface)) { - try { - Method equivalentMethod = iface.getMethod(method.getName(), method.getParameterTypes()); - annotation = getAnnotation(equivalentMethod, annotationType); - } catch (NoSuchMethodException ex) { - // Skip this interface - it doesn't have the method... - } - if (annotation != null) { - break; - } - } - } - return annotation; - } - - private static boolean isInterfaceWithAnnotatedMethods(Class iface) { - boolean found = false; - for (Method ifcMethod : iface.getMethods()) { - try { - if (ifcMethod.getAnnotations().length > 0) { - found = true; - break; - } - } catch (Exception ex) { - // Assuming nested Class values not resolvable within annotation attributes... - } - } - return found; - } - - /** - * Returns the property name for a method. - * This method is independent from property fields. - * - * @param method The method to get the property name for. - * @return the property name for given method; null if non could be resolved. - */ - public static String resolvePropertyName(Method method) { - - Matcher matcher = SETTER_PATTERN.matcher(method.getName()); - if (matcher.matches() && method.getParameterTypes().length == 1) { - String raw = matcher.group(1); - return raw.substring(0, 1).toLowerCase() + raw.substring(1); - } - - matcher = GETTER_PATTERN.matcher(method.getName()); - if (matcher.matches() && method.getParameterTypes().length == 0) { - String raw = matcher.group(2); - return raw.substring(0, 1).toLowerCase() + raw.substring(1); - } - - return null; - } - - /** - * Returns the annotation on the given class or the package of the class. This searchs up the - * class hierarchy and the package hierarchy for the closest match. - * - * @param class type - * @param clazz The class to search for the annotation. - * @param annotationClass The Class of the annotation. - * @return The annotation or null. - */ - public static T findAnnotation(Class clazz, Class annotationClass) { - T ann = clazz.getAnnotation(annotationClass); - while (ann == null && clazz != null) { - ann = clazz.getAnnotation(annotationClass); - if (ann == null) { - ann = clazz.getPackage().getAnnotation(annotationClass); - } - if (ann == null) { - clazz = clazz.getSuperclass(); - if (clazz != null) { - ann = clazz.getAnnotation(annotationClass); - } - } - } - - return ann; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/ClassPathFinder.java b/core/src/main/java/com/opensymphony/xwork2/util/ClassPathFinder.java deleted file mode 100644 index 289ab8c807..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/ClassPathFinder.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * $Id$ - * - * Copyright 2003-2004 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -import com.opensymphony.xwork2.XWorkException; - -import java.io.File; -import java.io.FileInputStream; -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.net.URL; -import java.net.URLClassLoader; -import java.util.HashMap; -import java.util.Vector; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - -/** - * This class is an utility class that will search through the classpath - * for files whose names match the given pattern. The filename is tested - * using the given implementation of {@link com.opensymphony.xwork2.util.PatternMatcher} by default it - * uses {@link com.opensymphony.xwork2.util.WildcardHelper} - */ -public class ClassPathFinder { - - /** - * The String pattern to test against. - */ - private String pattern ; - - private int[] compiledPattern ; - - /** - * The PatternMatcher implementation to use - */ - private PatternMatcher patternMatcher = new WildcardHelper(); - - private Vector compared = new Vector<>(); - - /** - * @return the pattern in use - */ - public String getPattern() { - return pattern; - } - - /** - * @param pattern the String pattern for comparing filenames - */ - public void setPattern(String pattern) { - this.pattern = pattern; - } - - /** - * Builds a {@link java.util.Vector} containing Strings which each name a file - * who's name matches the pattern set by setPattern(String). The classpath is - * searched recursively, so use with caution. - * - * @return Vector<String> containing matching filenames - */ - public Vector findMatches() { - Vector matches = new Vector<>(); - URLClassLoader cl = getURLClassLoader(); - if (cl == null ) { - throw new XWorkException("unable to attain an URLClassLoader") ; - } - URL[] parentUrls = cl.getURLs(); - compiledPattern = patternMatcher.compilePattern(pattern); - for (URL url : parentUrls) { - if (!"file".equals(url.getProtocol())) { - continue ; - } - URI entryURI ; - try { - entryURI = url.toURI(); - } catch (URISyntaxException e) { - continue; - } - File entry = new File(entryURI); - if (entry.isFile() && entry.toString().endsWith(".jar")) { - try { - ZipInputStream zip = new ZipInputStream(new FileInputStream(entry)); - for (ZipEntry zipEntry = zip.getNextEntry(); zipEntry != null; zipEntry = zip.getNextEntry()) { - boolean doesMatch = patternMatcher.match(new HashMap(), zipEntry.getName(), compiledPattern); - if (doesMatch) { - matches.add(zipEntry.getName()); - } - } - } catch (IOException e) { - e.printStackTrace(); - } - } else { - Vector results = checkEntries(entry.list(), entry, ""); - if (results != null) { - matches.addAll(results); - } - } - } - return matches; - } - - private Vector checkEntries(String[] entries, File parent, String prefix) { - - if (entries == null ) { - return null; - } - - Vector matches = new Vector<>(); - for (String listEntry : entries) { - File tempFile ; - if (!"".equals(prefix) ) { - tempFile = new File(parent, prefix + "/" + listEntry); - } - else { - tempFile = new File(parent, listEntry); - } - if (tempFile.isDirectory() && - !(".".equals(listEntry) || "..".equals(listEntry)) ) { - if (!"".equals(prefix) ) { - matches.addAll(checkEntries(tempFile.list(), parent, prefix + "/" + listEntry)); - } - else { - matches.addAll(checkEntries(tempFile.list(), parent, listEntry)); - } - } - else { - - String entryToCheck ; - if ("".equals(prefix)) { - entryToCheck = listEntry ; - } - else { - entryToCheck = prefix + "/" + listEntry ; - } - - if (compared.contains(entryToCheck) ) { - continue; - } - else { - compared.add(entryToCheck) ; - } - - boolean doesMatch = patternMatcher.match(new HashMap(), entryToCheck, compiledPattern); - if (doesMatch) { - matches.add(entryToCheck); - } - } - } - return matches ; - } - - /** - * @param patternMatcher the PatternMatcher implementation to use when comparing filenames - */ - public void setPatternMatcher(PatternMatcher patternMatcher) { - this.patternMatcher = patternMatcher; - } - - private URLClassLoader getURLClassLoader() { - URLClassLoader ucl = null; - ClassLoader loader = Thread.currentThread().getContextClassLoader(); - - if(! (loader instanceof URLClassLoader)) { - loader = ClassPathFinder.class.getClassLoader(); - if (loader instanceof URLClassLoader) { - ucl = (URLClassLoader) loader ; - } - } - else { - ucl = (URLClassLoader) loader; - } - - return ucl ; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/ClearableValueStack.java b/core/src/main/java/com/opensymphony/xwork2/util/ClearableValueStack.java deleted file mode 100644 index e4d129e94c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/ClearableValueStack.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * $Id$ - * - * Copyright 2003-2004 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -/** - * ValueStacks implementing this interface provide a way to remove values from - * their contexts. - */ -public interface ClearableValueStack { - /** - * Remove all values from the context - */ - void clearContextValues(); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/CompoundRoot.java b/core/src/main/java/com/opensymphony/xwork2/util/CompoundRoot.java deleted file mode 100644 index 49b47dad08..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/CompoundRoot.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -import java.util.List; -import java.util.concurrent.CopyOnWriteArrayList; - - -/** - * A Stack that is implemented using a List. - * - * @author plightbo - * @version $Revision$ - */ -public class CompoundRoot extends CopyOnWriteArrayList { - - private static final long serialVersionUID = 8563229069192473995L; - - public CompoundRoot() { - } - - public CompoundRoot(List list) { - super(list); - } - - - public CompoundRoot cutStack(int index) { - return new CompoundRoot(subList(index, size())); - } - - public Object peek() { - return get(0); - } - - public Object pop() { - return remove(0); - } - - public void push(Object o) { - add(0, o); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/CreateIfNull.java b/core/src/main/java/com/opensymphony/xwork2/util/CreateIfNull.java deleted file mode 100644 index 1511da737b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/CreateIfNull.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.util; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - *

    Sets the CreateIfNull for type conversion.

    - * - * - *

    Annotation usage:

    - * - * - *

    The CreateIfNull annotation must be applied at field or method level.

    - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    ParameterRequiredDefaultDescription
    valuenofalseThe CreateIfNull property value.
    - * - * - *

    Example code:

    - *
    - * 
    - * @CreateIfNull( value = true )
    - * private List<User> users;
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD, ElementType.METHOD}) -public @interface CreateIfNull { - - /** - * @return The CreateIfNull value. Defaults to true. - */ - boolean value() default true; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/DefaultLocalizedTextProvider.java b/core/src/main/java/com/opensymphony/xwork2/util/DefaultLocalizedTextProvider.java deleted file mode 100644 index c51521902f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/DefaultLocalizedTextProvider.java +++ /dev/null @@ -1,1039 +0,0 @@ -/* - * $Id$ - * - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -package com.opensymphony.xwork2.util; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.LocalizedTextProvider; -import com.opensymphony.xwork2.ModelDriven; -import com.opensymphony.xwork2.conversion.impl.XWorkConverter; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.reflection.ReflectionProviderFactory; -import org.apache.commons.lang3.ObjectUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.message.ParameterizedMessage; -import org.apache.struts2.StrutsConstants; - -import java.beans.PropertyDescriptor; -import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.text.MessageFormat; -import java.util.*; -import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.ConcurrentMap; -import java.util.concurrent.CopyOnWriteArrayList; - - -/** - * Provides support for localization in XWork. - * - * - *

    Resource bundles are searched in the following order:

    - * - *
      - *
    1. ActionClass.properties
    2. - *
    3. Interface.properties (every interface and sub-interface)
    4. - *
    5. BaseClass.properties (all the way to Object.properties)
    6. - *
    7. ModelDriven's model (if implements ModelDriven), for the model object repeat from 1
    8. - *
    9. package.properties (of the directory where class is located and every parent directory all the way to the root directory)
    10. - *
    11. search up the i18n message key hierarchy itself
    12. - *
    13. global resource properties
    14. - *
    - * - * - * - * - *

    To clarify #5, while traversing the package hierarchy, Struts 2 will look for a file package.properties:

    - * com/
    - *   acme/
    - *     package.properties
    - *     actions/
    - *       package.properties
    - *       FooAction.java
    - *       FooAction.properties
    - *

    - * If FooAction.properties does not exist, com/acme/action/package.properties will be searched for, if - * not found com/acme/package.properties, if not found com/package.properties, etc. - *

    - * - * - * - *

    - * A global resource bundle could be specified programmatically, as well as the locale. - *

    - * - * - * @author Jason Carreira - * @author Mark Woon - * @author Rainer Hermanns - * @author tm_jee - */ -public class DefaultLocalizedTextProvider implements LocalizedTextProvider { - - private static final Logger LOG = LogManager.getLogger(DefaultLocalizedTextProvider.class); - - public static final String XWORK_MESSAGES_BUNDLE = "com/opensymphony/xwork2/xwork-messages"; - public static final String STRUTS_MESSAGES_BUNDLE = "org/apache/struts2/struts-messages"; - - private static final String TOMCAT_RESOURCE_ENTRIES_FIELD = "resourceEntries"; - - private final ConcurrentMap> classLoaderMap = new ConcurrentHashMap<>(); - - private boolean reloadBundles = false; - private boolean devMode = false; - - private final ConcurrentMap bundlesMap = new ConcurrentHashMap<>(); - private final ConcurrentMap messageFormats = new ConcurrentHashMap<>(); - private final ConcurrentMap delegatedClassLoaderMap = new ConcurrentHashMap<>(); - private final Set missingBundles = Collections.synchronizedSet(new HashSet()); - - private final String RELOADED = "com.opensymphony.xwork2.util.LocalizedTextUtil.reloaded"; - - - /** - * Clears the internal list of resource bundles. - * - * @deprecated used only in tests - */ - @Deprecated - public static void clearDefaultResourceBundles() { - // no-op - } - - public DefaultLocalizedTextProvider() { - - addDefaultResourceBundle(XWORK_MESSAGES_BUNDLE); - addDefaultResourceBundle(STRUTS_MESSAGES_BUNDLE); - } - - /** - * Should resorce bundles be reloaded. - * - * @param reloadBundles reload bundles? - */ - @Inject(value = StrutsConstants.STRUTS_I18N_RELOAD, required = false) - public void setReloadBundles(String reloadBundles) { - this.reloadBundles = Boolean.parseBoolean(reloadBundles); - } - - @Inject(value = StrutsConstants.STRUTS_DEVMODE, required = false) - public void setDevMode(String devMode) { - this.devMode = Boolean.parseBoolean(devMode); - } - - @Inject(value = StrutsConstants.STRUTS_CUSTOM_I18N_RESOURCES, required = false) - public void setCustomI18NResources(String bundles) { - if (bundles != null && bundles.length() > 0) { - StringTokenizer customBundles = new StringTokenizer(bundles, ", "); - - while (customBundles.hasMoreTokens()) { - String name = customBundles.nextToken(); - try { - LOG.trace("Loading global messages from [{}]", name); - addDefaultResourceBundle(name); - } catch (Exception e) { - LOG.error(new ParameterizedMessage("Could not find messages file {}.properties. Skipping", name), e); - } - } - } - } - - /** - * Add's the bundle to the internal list of default bundles. - *

    - * If the bundle already exists in the list it will be readded. - *

    - * - * @param resourceBundleName the name of the bundle to add. - */ - @Override - public void addDefaultResourceBundle(String resourceBundleName) { - //make sure this doesn't get added more than once - final ClassLoader ccl = getCurrentThreadContextClassLoader(); - synchronized (XWORK_MESSAGES_BUNDLE) { - List bundles = classLoaderMap.get(ccl.hashCode()); - if (bundles == null) { - bundles = new CopyOnWriteArrayList<>(); - classLoaderMap.put(ccl.hashCode(), bundles); - } - bundles.remove(resourceBundleName); - bundles.add(0, resourceBundleName); - } - - if (LOG.isDebugEnabled()) { - LOG.debug("Added default resource bundle '{}' to default resource bundles for the following classloader '{}'", resourceBundleName, ccl.toString()); - } - } - - /** - * Builds a {@link java.util.Locale} from a String of the form en_US_foo into a Locale - * with language "en", country "US" and variant "foo". This will parse the output of - * {@link java.util.Locale#toString()}. - * - * @param localeStr The locale String to parse. - * @param defaultLocale The locale to use if localeStr is null. - * @return requested Locale - */ - public static Locale localeFromString(String localeStr, Locale defaultLocale) { - if ((localeStr == null) || (localeStr.trim().length() == 0) || ("_".equals(localeStr))) { - if (defaultLocale != null) { - return defaultLocale; - } - return Locale.getDefault(); - } - - int index = localeStr.indexOf('_'); - if (index < 0) { - return new Locale(localeStr); - } - - String language = localeStr.substring(0, index); - if (index == localeStr.length()) { - return new Locale(language); - } - - localeStr = localeStr.substring(index + 1); - index = localeStr.indexOf('_'); - if (index < 0) { - return new Locale(language, localeStr); - } - - String country = localeStr.substring(0, index); - if (index == localeStr.length()) { - return new Locale(language, country); - } - - localeStr = localeStr.substring(index + 1); - return new Locale(language, country, localeStr); - } - - /** - * Returns a localized message for the specified key, aTextName. Neither the key nor the - * message is evaluated. - * - * @param aTextName the message key - * @param locale the locale the message should be for - * @return a localized message based on the specified key, or null if no localized message can be found for it - */ - @Override - public String findDefaultText(String aTextName, Locale locale) { - List localList = classLoaderMap.get(Thread.currentThread().getContextClassLoader().hashCode()); - - for (String bundleName : localList) { - ResourceBundle bundle = findResourceBundle(bundleName, locale); - if (bundle != null) { - reloadBundles(); - try { - return bundle.getString(aTextName); - } catch (MissingResourceException e) { - // will be logged when not found in any bundle - } - } - } - - if (devMode) { - LOG.warn("Missing key [{}] in bundles [{}]!", aTextName, localList); - } else { - LOG.debug("Missing key [{}] in bundles [{}]!", aTextName, localList); - } - - return null; - } - - /** - * Returns a localized message for the specified key, aTextName, substituting variables from the - * array of params into the message. Neither the key nor the message is evaluated. - * - * @param aTextName the message key - * @param locale the locale the message should be for - * @param params an array of objects to be substituted into the message text - * @return A formatted message based on the specified key, or null if no localized message can be found for it - */ - @Override - public String findDefaultText(String aTextName, Locale locale, Object[] params) { - String defaultText = findDefaultText(aTextName, locale); - if (defaultText != null) { - MessageFormat mf = buildMessageFormat(defaultText, locale); - return formatWithNullDetection(mf, params); - } - return null; - } - - /** - * Finds the given resource bundle by it's name. - *

    - * Will use Thread.currentThread().getContextClassLoader() as the classloader. - *

    - * - * @param aBundleName the name of the bundle (usually it's FQN classname). - * @param locale the locale. - * @return the bundle, null if not found. - */ - @Override - public ResourceBundle findResourceBundle(String aBundleName, Locale locale) { - ClassLoader classLoader = getCurrentThreadContextClassLoader(); - String key = createMissesKey(String.valueOf(classLoader.hashCode()), aBundleName, locale); - - if (missingBundles.contains(key)) { - return null; - } - - ResourceBundle bundle = null; - try { - if (bundlesMap.containsKey(key)) { - bundle = bundlesMap.get(key); - } else { - bundle = ResourceBundle.getBundle(aBundleName, locale, classLoader); - bundlesMap.putIfAbsent(key, bundle); - } - } catch (MissingResourceException ex) { - if (delegatedClassLoaderMap.containsKey(classLoader.hashCode())) { - try { - if (bundlesMap.containsKey(key)) { - bundle = bundlesMap.get(key); - } else { - bundle = ResourceBundle.getBundle(aBundleName, locale, delegatedClassLoaderMap.get(classLoader.hashCode())); - bundlesMap.putIfAbsent(key, bundle); - } - } catch (MissingResourceException e) { - LOG.debug("Missing resource bundle [{}]!", aBundleName, e); - missingBundles.add(key); - } - } else { - LOG.debug("Missing resource bundle [{}]!", aBundleName); - missingBundles.add(key); - } - } - return bundle; - } - - /** - * @param classLoader a {@link ClassLoader} to look up the bundle from if none can be found on the current thread's classloader - */ - public void setDelegatedClassLoader(final ClassLoader classLoader) { - synchronized (bundlesMap) { - delegatedClassLoaderMap.put(getCurrentThreadContextClassLoader().hashCode(), classLoader); - } - } - - /** - * @param bundleName Removes the bundle from any cached "misses" - */ - public void clearBundle(final String bundleName) { - bundlesMap.remove(getCurrentThreadContextClassLoader().hashCode() + bundleName); - } - - - /** - * Creates a key to used for lookup/storing in the bundle misses cache. - * - * @param prefix the prefix for the returning String - it is supposed to be the ClassLoader hash code. - * @param aBundleName the name of the bundle (usually it's FQN classname). - * @param locale the locale. - * @return the key to use for lookup/storing in the bundle misses cache. - */ - private String createMissesKey(String prefix, String aBundleName, Locale locale) { - return prefix + aBundleName + "_" + locale.toString(); - } - - /** - * Calls {@link #findText(Class aClass, String aTextName, Locale locale, String defaultMessage, Object[] args)} - * with aTextName as the default message. - * - * @param aClass class name - * @param aTextName text name - * @param locale the locale - * - * @return the localized text, or null if none can be found and no defaultMessage is provided - * @see #findText(Class aClass, String aTextName, Locale locale, String defaultMessage, Object[] args) - */ - @Override - public String findText(Class aClass, String aTextName, Locale locale) { - return findText(aClass, aTextName, locale, aTextName, new Object[0]); - } - - /** - *

    - * Finds a localized text message for the given key, aTextName. Both the key and the message - * itself is evaluated as required. The following algorithm is used to find the requested - * message: - *

    - * - *
      - *
    1. Look for message in aClass' class hierarchy. - *
        - *
      1. Look for the message in a resource bundle for aClass
      2. - *
      3. If not found, look for the message in a resource bundle for any implemented interface
      4. - *
      5. If not found, traverse up the Class' hierarchy and repeat from the first sub-step
      6. - *
    2. - *
    3. If not found and aClass is a {@link ModelDriven} Action, then look for message in - * the model's class hierarchy (repeat sub-steps listed above).
    4. - *
    5. If not found, look for message in child property. This is determined by evaluating - * the message key as an OGNL expression. For example, if the key is - * user.address.state, then it will attempt to see if "user" can be resolved into an - * object. If so, repeat the entire process fromthe beginning with the object's class as - * aClass and "address.state" as the message key.
    6. - *
    7. If not found, look for the message in aClass' package hierarchy.
    8. - *
    9. If still not found, look for the message in the default resource bundles.
    10. - *
    11. Return defaultMessage
    12. - *
    - * - *

    - * When looking for the message, if the key indexes a collection (e.g. user.phone[0]) and a - * message for that specific key cannot be found, the general form will also be looked up - * (i.e. user.phone[*]). - *

    - * - *

    - * If a message is found, it will also be interpolated. Anything within ${...} - * will be treated as an OGNL expression and evaluated as such. - *

    - * - * @param aClass the class whose name to use as the start point for the search - * @param aTextName the key to find the text message for - * @param locale the locale the message should be for - * @param defaultMessage the message to be returned if no text message can be found in any - * resource bundle - * @param args arguments - * resource bundle - * @return the localized text, or null if none can be found and no defaultMessage is provided - */ - @Override - public String findText(Class aClass, String aTextName, Locale locale, String defaultMessage, Object[] args) { - ValueStack valueStack = ActionContext.getContext().getValueStack(); - return findText(aClass, aTextName, locale, defaultMessage, args, valueStack); - - } - - /** - *

    - * Finds a localized text message for the given key, aTextName. Both the key and the message - * itself is evaluated as required. The following algorithm is used to find the requested - * message: - *

    - * - *
      - *
    1. Look for message in aClass' class hierarchy. - *
        - *
      1. Look for the message in a resource bundle for aClass
      2. - *
      3. If not found, look for the message in a resource bundle for any implemented interface
      4. - *
      5. If not found, traverse up the Class' hierarchy and repeat from the first sub-step
      6. - *
    2. - *
    3. If not found and aClass is a {@link ModelDriven} Action, then look for message in - * the model's class hierarchy (repeat sub-steps listed above).
    4. - *
    5. If not found, look for message in child property. This is determined by evaluating - * the message key as an OGNL expression. For example, if the key is - * user.address.state, then it will attempt to see if "user" can be resolved into an - * object. If so, repeat the entire process fromthe beginning with the object's class as - * aClass and "address.state" as the message key.
    6. - *
    7. If not found, look for the message in aClass' package hierarchy.
    8. - *
    9. If still not found, look for the message in the default resource bundles.
    10. - *
    11. Return defaultMessage
    12. - *
    - * - *

    - * When looking for the message, if the key indexes a collection (e.g. user.phone[0]) and a - * message for that specific key cannot be found, the general form will also be looked up - * (i.e. user.phone[*]). - *

    - * - *

    - * If a message is found, it will also be interpolated. Anything within ${...} - * will be treated as an OGNL expression and evaluated as such. - *

    - * - *

    - * If a message is not found a WARN log will be logged. - *

    - * - * @param aClass the class whose name to use as the start point for the search - * @param aTextName the key to find the text message for - * @param locale the locale the message should be for - * @param defaultMessage the message to be returned if no text message can be found in any - * resource bundle - * @param args arguments - * @param valueStack the value stack to use to evaluate expressions instead of the - * one in the ActionContext ThreadLocal - * @return the localized text, or null if none can be found and no defaultMessage is provided - */ - @Override - public String findText(Class aClass, String aTextName, Locale locale, String defaultMessage, Object[] args, - ValueStack valueStack) { - String indexedTextName = null; - if (aTextName == null) { - LOG.warn("Trying to find text with null key!"); - aTextName = ""; - } - // calculate indexedTextName (collection[*]) if applicable - if (aTextName.contains("[")) { - int i = -1; - - indexedTextName = aTextName; - - while ((i = indexedTextName.indexOf("[", i + 1)) != -1) { - int j = indexedTextName.indexOf("]", i); - String a = indexedTextName.substring(0, i); - String b = indexedTextName.substring(j); - indexedTextName = a + "[*" + b; - } - } - - // search up class hierarchy - String msg = findMessage(aClass, aTextName, indexedTextName, locale, args, null, valueStack); - - if (msg != null) { - return msg; - } - - if (ModelDriven.class.isAssignableFrom(aClass)) { - ActionContext context = ActionContext.getContext(); - // search up model's class hierarchy - ActionInvocation actionInvocation = context.getActionInvocation(); - - // ActionInvocation may be null if we're being run from a Sitemesh filter, so we won't get model texts if this is null - if (actionInvocation != null) { - Object action = actionInvocation.getAction(); - if (action instanceof ModelDriven) { - Object model = ((ModelDriven) action).getModel(); - if (model != null) { - msg = findMessage(model.getClass(), aTextName, indexedTextName, locale, args, null, valueStack); - if (msg != null) { - return msg; - } - } - } - } - } - - // nothing still? alright, search the package hierarchy now - for (Class clazz = aClass; - (clazz != null) && !clazz.equals(Object.class); - clazz = clazz.getSuperclass()) { - - String basePackageName = clazz.getName(); - while (basePackageName.lastIndexOf('.') != -1) { - basePackageName = basePackageName.substring(0, basePackageName.lastIndexOf('.')); - String packageName = basePackageName + ".package"; - msg = getMessage(packageName, locale, aTextName, valueStack, args); - - if (msg != null) { - return msg; - } - - if (indexedTextName != null) { - msg = getMessage(packageName, locale, indexedTextName, valueStack, args); - - if (msg != null) { - return msg; - } - } - } - } - - // see if it's a child property - int idx = aTextName.indexOf("."); - - if (idx != -1) { - String newKey = null; - String prop = null; - - if (aTextName.startsWith(XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX)) { - idx = aTextName.indexOf(".", XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX.length()); - - if (idx != -1) { - prop = aTextName.substring(XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX.length(), idx); - newKey = XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX + aTextName.substring(idx + 1); - } - } else { - prop = aTextName.substring(0, idx); - newKey = aTextName.substring(idx + 1); - } - - if (prop != null) { - Object obj = valueStack.findValue(prop); - try { - Object actionObj = ReflectionProviderFactory.getInstance().getRealTarget(prop, valueStack.getContext(), valueStack.getRoot()); - if (actionObj != null) { - PropertyDescriptor propertyDescriptor = ReflectionProviderFactory.getInstance().getPropertyDescriptor(actionObj.getClass(), prop); - - if (propertyDescriptor != null) { - Class clazz = propertyDescriptor.getPropertyType(); - - if (clazz != null) { - if (obj != null) { - valueStack.push(obj); - } - msg = findText(clazz, newKey, locale, null, args); - if (obj != null) { - valueStack.pop(); - } - if (msg != null) { - return msg; - } - } - } - } - } catch (Exception e) { - LOG.debug("unable to find property {}", prop, e); - } - } - } - - // get default - GetDefaultMessageReturnArg result; - if (indexedTextName == null) { - result = getDefaultMessage(aTextName, locale, valueStack, args, defaultMessage); - } else { - result = getDefaultMessage(aTextName, locale, valueStack, args, null); - if (result != null && result.message != null) { - return result.message; - } - result = getDefaultMessage(indexedTextName, locale, valueStack, args, defaultMessage); - } - - // could we find the text, if not log a warn - if (unableToFindTextForKey(result) && LOG.isDebugEnabled()) { - String warn = "Unable to find text for key '" + aTextName + "' "; - if (indexedTextName != null) { - warn += " or indexed key '" + indexedTextName + "' "; - } - warn += "in class '" + aClass.getName() + "' and locale '" + locale + "'"; - LOG.debug(warn); - } - - return result != null ? result.message : null; - } - - /** - * Determines if we found the text in the bundles. - * - * @param result the result so far - * @return true if we could not find the text, false if the text was found (=success). - */ - private static boolean unableToFindTextForKey(GetDefaultMessageReturnArg result) { - if (result == null || result.message == null) { - return true; - } - - // did we find it in the bundle, then no problem? - if (result.foundInBundle) { - return false; - } - - // not found in bundle - return true; - } - - /** - *

    - * Finds a localized text message for the given key, aTextName, in the specified resource bundle - * with aTextName as the default message. - *

    - * - *

    - * If a message is found, it will also be interpolated. Anything within ${...} - * will be treated as an OGNL expression and evaluated as such. - *

    - * - * @param bundle a resource bundle name - * @param aTextName text name - * @param locale the locale - * - * @return the localized text, or null if none can be found and no defaultMessage is provided - * @see #findText(java.util.ResourceBundle, String, java.util.Locale, String, Object[]) - */ - @Override - public String findText(ResourceBundle bundle, String aTextName, Locale locale) { - return findText(bundle, aTextName, locale, aTextName, new Object[0]); - } - - /** - *

    - * Finds a localized text message for the given key, aTextName, in the specified resource - * bundle. - *

    - * - *

    - * If a message is found, it will also be interpolated. Anything within ${...} - * will be treated as an OGNL expression and evaluated as such. - *

    - * - *

    - * If a message is not found a WARN log will be logged. - *

    - * - * @param bundle the bundle - * @param aTextName the key - * @param locale the locale - * @param defaultMessage the default message to use if no message was found in the bundle - * @param args arguments for the message formatter. - * @return the localized text, or null if none can be found and no defaultMessage is provided - */ - @Override - public String findText(ResourceBundle bundle, String aTextName, Locale locale, String defaultMessage, Object[] args) { - ValueStack valueStack = ActionContext.getContext().getValueStack(); - return findText(bundle, aTextName, locale, defaultMessage, args, valueStack); - } - - /** - *

    - * Finds a localized text message for the given key, aTextName, in the specified resource - * bundle. - *

    - * - *

    - * If a message is found, it will also be interpolated. Anything within ${...} - * will be treated as an OGNL expression and evaluated as such. - *

    - * - *

    - * If a message is not found a WARN log will be logged. - *

    - * - * @param bundle the bundle - * @param aTextName the key - * @param locale the locale - * @param defaultMessage the default message to use if no message was found in the bundle - * @param args arguments for the message formatter. - * @param valueStack the OGNL value stack. - * @return the localized text, or null if none can be found and no defaultMessage is provided - */ - @Override - public String findText(ResourceBundle bundle, String aTextName, Locale locale, String defaultMessage, Object[] args, - ValueStack valueStack) { - try { - reloadBundles(valueStack.getContext()); - - String message = TextParseUtil.translateVariables(bundle.getString(aTextName), valueStack); - MessageFormat mf = buildMessageFormat(message, locale); - - return formatWithNullDetection(mf, args); - } catch (MissingResourceException ex) { - if (devMode) { - LOG.warn("Missing key [{}] in bundle [{}]!", aTextName, bundle); - } else { - LOG.debug("Missing key [{}] in bundle [{}]!", aTextName, bundle); - } - } - - GetDefaultMessageReturnArg result = getDefaultMessage(aTextName, locale, valueStack, args, defaultMessage); - if (unableToFindTextForKey(result)) { - LOG.warn("Unable to find text for key '{}' in ResourceBundles for locale '{}'", aTextName, locale); - } - return result != null ? result.message : null; - } - - /** - * @return the default message. - */ - private GetDefaultMessageReturnArg getDefaultMessage(String key, Locale locale, ValueStack valueStack, Object[] args, - String defaultMessage) { - GetDefaultMessageReturnArg result = null; - boolean found = true; - - if (key != null) { - String message = findDefaultText(key, locale); - - if (message == null) { - message = defaultMessage; - found = false; // not found in bundles - } - - // defaultMessage may be null - if (message != null) { - MessageFormat mf = buildMessageFormat(TextParseUtil.translateVariables(message, valueStack), locale); - - String msg = formatWithNullDetection(mf, args); - result = new GetDefaultMessageReturnArg(msg, found); - } - } - - return result; - } - - /** - * @return the message from the named resource bundle. - */ - private String getMessage(String bundleName, Locale locale, String key, ValueStack valueStack, Object[] args) { - ResourceBundle bundle = findResourceBundle(bundleName, locale); - if (bundle == null) { - return null; - } - if (valueStack != null) - reloadBundles(valueStack.getContext()); - try { - String message = bundle.getString(key); - if (valueStack != null) - message = TextParseUtil.translateVariables(bundle.getString(key), valueStack); - MessageFormat mf = buildMessageFormat(message, locale); - return formatWithNullDetection(mf, args); - } catch (MissingResourceException e) { - if (devMode) { - LOG.warn("Missing key [{}] in bundle [{}]!", key, bundleName); - } else { - LOG.debug("Missing key [{}] in bundle [{}]!", key, bundleName); - } - return null; - } - } - - private String formatWithNullDetection(MessageFormat mf, Object[] args) { - String message = mf.format(args); - if ("null".equals(message)) { - return null; - } else { - return message; - } - } - - private MessageFormat buildMessageFormat(String pattern, Locale locale) { - MessageFormatKey key = new MessageFormatKey(pattern, locale); - MessageFormat format = messageFormats.get(key); - if (format == null) { - format = new MessageFormat(pattern); - format.setLocale(locale); - format.applyPattern(pattern); - messageFormats.put(key, format); - } - - return format; - } - - /** - * Traverse up class hierarchy looking for message. Looks at class, then implemented interface, - * before going up hierarchy. - * - * @return the message - */ - private String findMessage(Class clazz, String key, String indexedKey, Locale locale, Object[] args, Set checked, - ValueStack valueStack) { - if (checked == null) { - checked = new TreeSet(); - } else if (checked.contains(clazz.getName())) { - return null; - } - - // look in properties of this class - String msg = getMessage(clazz.getName(), locale, key, valueStack, args); - - if (msg != null) { - return msg; - } - - if (indexedKey != null) { - msg = getMessage(clazz.getName(), locale, indexedKey, valueStack, args); - - if (msg != null) { - return msg; - } - } - - // look in properties of implemented interfaces - Class[] interfaces = clazz.getInterfaces(); - - for (Class anInterface : interfaces) { - msg = getMessage(anInterface.getName(), locale, key, valueStack, args); - - if (msg != null) { - return msg; - } - - if (indexedKey != null) { - msg = getMessage(anInterface.getName(), locale, indexedKey, valueStack, args); - - if (msg != null) { - return msg; - } - } - } - - // traverse up hierarchy - if (clazz.isInterface()) { - interfaces = clazz.getInterfaces(); - - for (Class anInterface : interfaces) { - msg = findMessage(anInterface, key, indexedKey, locale, args, checked, valueStack); - - if (msg != null) { - return msg; - } - } - } else { - if (!clazz.equals(Object.class) && !clazz.isPrimitive()) { - return findMessage(clazz.getSuperclass(), key, indexedKey, locale, args, checked, valueStack); - } - } - - return null; - } - - private void reloadBundles() { - reloadBundles(ActionContext.getContext() != null ? ActionContext.getContext().getContextMap() : null); - } - - private void reloadBundles(Map context) { - if (reloadBundles) { - try { - Boolean reloaded; - if (context != null) { - reloaded = (Boolean) ObjectUtils.defaultIfNull(context.get(RELOADED), Boolean.FALSE); - }else { - reloaded = Boolean.FALSE; - } - if (!reloaded) { - bundlesMap.clear(); - try { - clearMap(ResourceBundle.class, null, "cacheList"); - } catch (NoSuchFieldException e) { - // happens in IBM JVM, that has a different ResourceBundle impl - // it has a 'cache' member - clearMap(ResourceBundle.class, null, "cache"); - } - - // now, for the true and utter hack, if we're running in tomcat, clear - // it's class loader resource cache as well. - clearTomcatCache(); - if(context!=null) { - context.put(RELOADED, true); - } - LOG.debug("Resource bundles reloaded"); - } - } catch (Exception e) { - LOG.error("Could not reload resource bundles", e); - } - } - } - - - private static void clearTomcatCache() { - ClassLoader loader = getCurrentThreadContextClassLoader(); - // no need for compilation here. - Class cl = loader.getClass(); - - try { - if ("org.apache.catalina.loader.WebappClassLoader".equals(cl.getName())) { - clearMap(cl, loader, TOMCAT_RESOURCE_ENTRIES_FIELD); - } else { - LOG.debug("Class loader {} is not tomcat loader.", cl.getName()); - } - } catch (NoSuchFieldException nsfe) { - if ("org.apache.catalina.loader.WebappClassLoaderBase".equals(cl.getSuperclass().getName())) { - LOG.debug("Base class {} doesn't contain '{}' field, trying with parent!", cl.getName(), TOMCAT_RESOURCE_ENTRIES_FIELD, nsfe); - try { - clearMap(cl.getSuperclass(), loader, TOMCAT_RESOURCE_ENTRIES_FIELD); - } catch (Exception e) { - LOG.warn("Couldn't clear tomcat cache using {}", cl.getSuperclass().getName(), e); - } - } - } catch (Exception e) { - LOG.warn("Couldn't clear tomcat cache", cl.getName(), e); - } - } - - - private static void clearMap(Class cl, Object obj, String name) - throws NoSuchFieldException, IllegalAccessException, NoSuchMethodException, InvocationTargetException { - - Field field = cl.getDeclaredField(name); - field.setAccessible(true); - - Object cache = field.get(obj); - - synchronized (cache) { - Class ccl = cache.getClass(); - Method clearMethod = ccl.getMethod("clear"); - clearMethod.invoke(cache); - } - } - - /** - * Clears all the internal lists. - * - * @deprecated used only in tests - */ - @Deprecated - public void reset() { - // no-op - } - - static class MessageFormatKey { - String pattern; - Locale locale; - - MessageFormatKey(String pattern, Locale locale) { - this.pattern = pattern; - this.locale = locale; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof MessageFormatKey)) return false; - - final MessageFormatKey messageFormatKey = (MessageFormatKey) o; - - if (locale != null ? !locale.equals(messageFormatKey.locale) : messageFormatKey.locale != null) - return false; - if (pattern != null ? !pattern.equals(messageFormatKey.pattern) : messageFormatKey.pattern != null) - return false; - - return true; - } - - @Override - public int hashCode() { - int result; - result = (pattern != null ? pattern.hashCode() : 0); - result = 29 * result + (locale != null ? locale.hashCode() : 0); - return result; - } - } - - private static ClassLoader getCurrentThreadContextClassLoader() { - return Thread.currentThread().getContextClassLoader(); - } - - static class GetDefaultMessageReturnArg { - String message; - boolean foundInBundle; - - public GetDefaultMessageReturnArg(String message, boolean foundInBundle) { - this.message = message; - this.foundInBundle = foundInBundle; - } - } - - private static class EmptyResourceBundle extends ResourceBundle { - @Override - public Enumeration getKeys() { - return null; // dummy - } - - @Override - protected Object handleGetObject(String key) { - return null; // dummy - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/Element.java b/core/src/main/java/com/opensymphony/xwork2/util/Element.java deleted file mode 100644 index 1b41f57719..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/Element.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.util; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - *

    Sets the Element for type conversion.

    - * - * - *

    Annotation usage:

    - * - * - *

    The Element annotation must be applied at field or method level.

    - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    ParameterRequiredDefaultDescription
    valuenojava.lang.Object.classThe element property value.
    - * - * - *

    Example code:

    - *
    - * 
    - * // The key property for User objects within the users collection is the userName attribute.
    - * @Element( value = com.acme.User )
    - * private Map<Long, User> userMap;
    - *
    - * @Element( value = com.acme.User )
    - * public List<User> userList;
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD, ElementType.METHOD}) -public @interface Element { - - /** - * @return The Element value. Defaults to java.lang.Object.class. - */ - Class value() default java.lang.Object.class; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/Evaluated.java b/core/src/main/java/com/opensymphony/xwork2/util/Evaluated.java deleted file mode 100644 index 219e85cc21..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/Evaluated.java +++ /dev/null @@ -1,18 +0,0 @@ -package com.opensymphony.xwork2.util; - -public class Evaluated { - - private Object value; - - public Evaluated(Object value) { - this.value = value; - } - - public boolean isDefined() { - return value != null; - } - - public Object get() { - return value; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/Key.java b/core/src/main/java/com/opensymphony/xwork2/util/Key.java deleted file mode 100644 index 0448b3fbfb..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/Key.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.util; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - *

    Sets the Key for type conversion.

    - * - * - *

    Annotation usage:

    - * - * - *

    The Key annotation must be applied at field or method level.

    - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    ParameterRequiredDefaultDescription
    valuenojava.lang.Object.classThe key property value.
    - * - * - *

    Example code:

    - *
    - * 
    - * // The key property for User objects within the users collection is the userName attribute.
    - * @Key( value = java.lang.Long.class )
    - * private Map<Long, User> userMap;
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD, ElementType.METHOD}) -public @interface Key { - - /** - * @return The Key value. Defaults to java.lang.Object.class. - */ - Class value() default java.lang.Object.class; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/KeyProperty.java b/core/src/main/java/com/opensymphony/xwork2/util/KeyProperty.java deleted file mode 100644 index 1a702ba77a..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/KeyProperty.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.util; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - *

    Sets the KeyProperty for type conversion.

    - * - * - *

    Annotation usage:

    - * - * - *

    The KeyProperty annotation must be applied at field or method level.

    - *

    This annotation should be used with Generic types, if the key property of the key element needs to be specified.

    - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    ParameterRequiredDefaultDescription
    valuenoidThe key property value.
    - * - * - *

    Example code:

    - *
    - * 
    - * // The key property for User objects within the users collection is the userName attribute.
    - * @KeyProperty( value = "userName" )
    - * protected List<User> users = null;
    - * 
    - * 
    - * - * @author Patrick Lightbody - * @author Rainer Hermanns - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ElementType.FIELD, ElementType.METHOD}) -public @interface KeyProperty { - - /** - * @return The KeyProperty value. Defaults to the id attribute. - */ - String value() default "id"; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/MemberAccessValueStack.java b/core/src/main/java/com/opensymphony/xwork2/util/MemberAccessValueStack.java deleted file mode 100644 index 51f4e489c2..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/MemberAccessValueStack.java +++ /dev/null @@ -1,16 +0,0 @@ -package com.opensymphony.xwork2.util; - -import java.util.Set; -import java.util.regex.Pattern; - -/** - * ValueStacks implementing this interface provide a way to remove block or allow access - * to properties using regular expressions - */ -public interface MemberAccessValueStack { - - void setExcludeProperties(Set excludeProperties); - - void setAcceptProperties(Set acceptedProperties); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java b/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java deleted file mode 100644 index 3e640cb65f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/NamedVariablePatternMatcher.java +++ /dev/null @@ -1,146 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * An implementation of a pattern matcher that uses simple named wildcards. The named wildcards are defined using the - * {VARIABLE_NAME} syntax and will match any characters that aren't '/'. Internally, the pattern is - * converted into a regular expression where the named wildcard will be translated into ([^/]+) so that - * at least one character must match in order for the wildcard to be matched successfully. Matched values will be - * available in the variable map, indexed by the name they were given in the pattern. - * - *

    For example, the following patterns will be processed as so:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    PatternExampleVariable Map Contents
    /animals/{animal}/animals/dog{animal -> dog}
    /animals/{animal}/tag/No{id}/animals/dog/tag/No23{animal -> dog, id -> 23}
    /{language}/en{language -> en}
    - * - *

    - * Excaping hasn't been implemented since the intended use of these patterns will be in matching URLs. - *

    - * - * @since 2.1 - */ -public class NamedVariablePatternMatcher implements PatternMatcher { - - public boolean isLiteral(String pattern) { - return (pattern == null || pattern.indexOf('{') == -1); - } - - /** - * Compiles the pattern. - * - * @param data The pattern, must not be null or empty - * @return The compiled pattern, null if the pattern was null or empty - */ - public CompiledPattern compilePattern(String data) { - StringBuilder regex = new StringBuilder(); - if (data != null && data.length() > 0) { - List varNames = new ArrayList<>(); - StringBuilder varName = null; - for (int x=0; x map, String data, CompiledPattern expr) { - - if (data != null && data.length() > 0) { - Matcher matcher = expr.getPattern().matcher(data); - if (matcher.matches()) { - for (int x=0; x variableNames; - - - public CompiledPattern(Pattern pattern, List variableNames) { - this.pattern = pattern; - this.variableNames = variableNames; - } - - public Pattern getPattern() { - return pattern; - } - - public List getVariableNames() { - return variableNames; - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/OgnlTextParser.java b/core/src/main/java/com/opensymphony/xwork2/util/OgnlTextParser.java deleted file mode 100644 index 899c3754d0..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/OgnlTextParser.java +++ /dev/null @@ -1,83 +0,0 @@ -package com.opensymphony.xwork2.util; - -import org.apache.commons.lang3.StringUtils; - -/** - * OGNL implementation of {@link TextParser} - */ -public class OgnlTextParser implements TextParser { - - public Object evaluate(char[] openChars, String expression, TextParseUtil.ParsedValueEvaluator evaluator, int maxLoopCount) { - // deal with the "pure" expressions first! - //expression = expression.trim(); - Object result = expression = (expression == null) ? "" : expression; - int pos = 0; - - for (char open : openChars) { - int loopCount = 1; - //this creates an implicit StringBuffer and shouldn't be used in the inner loop - final String lookupChars = open + "{"; - - while (true) { - int start = expression.indexOf(lookupChars, pos); - if (start == -1) { - loopCount++; - start = expression.indexOf(lookupChars); - } - if (loopCount > maxLoopCount) { - // translateVariables prevent infinite loop / expression recursive evaluation - break; - } - int length = expression.length(); - int x = start + 2; - int end; - char c; - int count = 1; - while (start != -1 && x < length && count != 0) { - c = expression.charAt(x++); - if (c == '{') { - count++; - } else if (c == '}') { - count--; - } - } - end = x - 1; - - if ((start != -1) && (end != -1) && (count == 0)) { - String var = expression.substring(start + 2, end); - - Object o = evaluator.evaluate(var); - - String left = expression.substring(0, start); - String right = expression.substring(end + 1); - String middle = null; - if (o != null) { - middle = o.toString(); - if (StringUtils.isEmpty(left)) { - result = o; - } else { - result = left.concat(middle); - } - - if (StringUtils.isNotEmpty(right)) { - result = result.toString().concat(right); - } - - expression = left.concat(middle).concat(right); - } else { - // the variable doesn't exist, so don't display anything - expression = left.concat(right); - result = expression; - } - pos = (left != null && left.length() > 0 ? left.length() - 1: 0) + - (middle != null && middle.length() > 0 ? middle.length() - 1: 0) + - 1; - pos = Math.max(pos, 1); - } else { - break; - } - } - } - return result; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/PatternMatcher.java b/core/src/main/java/com/opensymphony/xwork2/util/PatternMatcher.java deleted file mode 100644 index f4728930d3..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/PatternMatcher.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * $Id$ - * - * Copyright 2003-2004 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -import java.util.Map; - -/** - * Compiles and matches a pattern against a value - * - * @since 2.1 - */ -public interface PatternMatcher { - - /** - * Determines if the pattern is a simple literal string or contains wildcards that will need to be processed - * @param pattern The string pattern - * @return True if the pattern doesn't contain processing elements, false otherwise - */ - boolean isLiteral(String pattern); - - /** - *

    Translate the given String into an object - * representing the pattern matchable by this class. - * - * @param data The string to translate. - * @return The encoded string - * @throws NullPointerException If data is null. - */ - E compilePattern(String data); - - /** - * Match a pattern against a string - * - * @param map The map to store matched values - * @param data The string to match - * @param expr The compiled wildcard expression - * @return True if a match - * @throws NullPointerException If any parameters are null - */ - boolean match(Map map, String data, E expr); - -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/util/TextParser.java b/core/src/main/java/com/opensymphony/xwork2/util/TextParser.java deleted file mode 100644 index 2f53bb02d0..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/TextParser.java +++ /dev/null @@ -1,13 +0,0 @@ -package com.opensymphony.xwork2.util; - -/** - * Used to parse expressions like ${foo.bar} or %{bar.foo} but it is up tp the TextParser's - * implementation what kind of opening char to use (#, $, %, etc) - */ -public interface TextParser { - - int DEFAULT_LOOP_COUNT = 1; - - Object evaluate(char[] openChars, String expression, TextParseUtil.ParsedValueEvaluator evaluator, int maxLoopCount); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/ValueStack.java b/core/src/main/java/com/opensymphony/xwork2/util/ValueStack.java deleted file mode 100644 index 3bfe0ff9be..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/ValueStack.java +++ /dev/null @@ -1,159 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -import java.util.Map; - -/** - * ValueStack allows multiple beans to be pushed in and dynamic EL expressions to be evaluated against it. When - * evaluating an expression, the stack will be searched down the stack, from the latest objects pushed in to the - * earliest, looking for a bean with a getter or setter for the given property or a method of the given name (depending - * on the expression being evaluated). - */ -public interface ValueStack { - - public static final String VALUE_STACK = "com.opensymphony.xwork2.util.ValueStack.ValueStack"; - - public static final String REPORT_ERRORS_ON_NO_PROP = "com.opensymphony.xwork2.util.ValueStack.ReportErrorsOnNoProp"; - - /** - * Gets the context for this value stack. The context holds all the information in the value stack and it's surroundings. - * - * @return the context. - */ - public abstract Map getContext(); - - /** - * Sets the default type to convert to if no type is provided when getting a value. - * - * @param defaultType the new default type - */ - public abstract void setDefaultType(Class defaultType); - - /** - * Set a override map containing key -> values that takes precedent when doing find operations on the ValueStack. - *

    - * See the unit test for ValueStackTest for examples. - *

    - * - * @param overrides overrides map. - */ - public abstract void setExprOverrides(Map overrides); - - /** - * Gets the override map if anyone exists. - * - * @return the override map, null if not set. - */ - public abstract Map getExprOverrides(); - - /** - * Get the CompoundRoot which holds the objects pushed onto the stack - * - * @return the root - */ - public abstract CompoundRoot getRoot(); - - /** - * Attempts to set a property on a bean in the stack with the given expression using the default search order. - * - * @param expr the expression defining the path to the property to be set. - * @param value the value to be set into the named property - */ - public abstract void setValue(String expr, Object value); - - /** - * Attempts to set a property on a bean in the stack with the given expression using the default search order. - * N.B.: unlike #setValue(String,Object) it doesn't allow eval expression. - * @param expr the expression defining the path to the property to be set. - * @param value the value to be set into the named property - */ - void setParameter(String expr, Object value); - - /** - * Attempts to set a property on a bean in the stack with the given expression using the default search order. - * - * @param expr the expression defining the path to the property to be set. - * @param value the value to be set into the named property - * @param throwExceptionOnFailure a flag to tell whether an exception should be thrown if there is no property with - * the given name. - */ - public abstract void setValue(String expr, Object value, boolean throwExceptionOnFailure); - - public abstract String findString(String expr); - public abstract String findString(String expr, boolean throwExceptionOnFailure); - - /** - * Find a value by evaluating the given expression against the stack in the default search order. - * - * @param expr the expression giving the path of properties to navigate to find the property value to return - * @return the result of evaluating the expression - */ - public abstract Object findValue(String expr); - - public abstract Object findValue(String expr, boolean throwExceptionOnFailure); - - /** - * Find a value by evaluating the given expression against the stack in the default search order. - * - * @param expr the expression giving the path of properties to navigate to find the property value to return - * @param asType the type to convert the return value to - * @return the result of evaluating the expression - */ - public abstract Object findValue(String expr, Class asType); - public abstract Object findValue(String expr, Class asType, boolean throwExceptionOnFailure); - - /** - * Get the object on the top of the stack without changing the stack. - * - * @return the object on the top. - * @see CompoundRoot#peek() - */ - public abstract Object peek(); - - /** - * Get the object on the top of the stack and remove it from the stack. - * - * @return the object on the top of the stack - * @see CompoundRoot#pop() - */ - public abstract Object pop(); - - /** - * Put this object onto the top of the stack - * - * @param o the object to be pushed onto the stack - * @see CompoundRoot#push(Object) - */ - public abstract void push(Object o); - - /** - * Sets an object on the stack with the given key - * so it is retrievable by {@link #findValue(String)}, {@link #findValue(String, Class)} - * - * @param key the key - * @param o the object - */ - public abstract void set(String key, Object o); - - /** - * Get the number of objects in the stack - * - * @return the number of objects in the stack - */ - public abstract int size(); - -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/util/ValueStackFactory.java b/core/src/main/java/com/opensymphony/xwork2/util/ValueStackFactory.java deleted file mode 100644 index aa8256d680..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/ValueStackFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -/** - * Factory that creates a value stack, defaulting to the OgnlValueStackFactory - */ -public interface ValueStackFactory { - - /** - * Get a new instance of {@link com.opensymphony.xwork2.util.ValueStack} - * - * @return a new {@link com.opensymphony.xwork2.util.ValueStack}. - */ - ValueStack createValueStack(); - - /** - * Get a new instance of {@link com.opensymphony.xwork2.util.ValueStack} - * - * @param stack an existing stack to include. - * @return a new {@link com.opensymphony.xwork2.util.ValueStack}. - */ - ValueStack createValueStack(ValueStack stack); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/WildcardHelper.java b/core/src/main/java/com/opensymphony/xwork2/util/WildcardHelper.java deleted file mode 100644 index 86a3b9a807..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/WildcardHelper.java +++ /dev/null @@ -1,463 +0,0 @@ -/* - * $Id$ - * - * Copyright 2003-2004 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -import java.util.Map; - -/** - * This class is an utility class that perform wilcard-patterns matching and - * isolation taken from Apache Cocoon. - * - * @version $Rev$ $Date: 2005-05-07 12:11:38 -0400 (Sat, 07 May 2005) - * $ - */ -public class WildcardHelper implements PatternMatcher { - /** - * The int representing '*' in the pattern int []. - */ - protected static final int MATCH_FILE = -1; - - /** - * The int representing '**' in the pattern int []. - */ - protected static final int MATCH_PATH = -2; - - /** - * The int representing begin in the pattern int []. - */ - protected static final int MATCH_BEGIN = -4; - - /** - * The int representing end in pattern int []. - */ - protected static final int MATCH_THEEND = -5; - - /** - * The int value that terminates the pattern int []. - */ - protected static final int MATCH_END = -3; - - /** - * Determines if the pattern contains any * characters - * - * @param pattern The pattern - * @return True if no wildcards are found - */ - public boolean isLiteral(String pattern) { - return (pattern == null || pattern.indexOf('*') == -1); - } - - /** - *

    Translate the given String into a int [] - * representing the pattern matchable by this class.
    This function - * translates a String into an int array converting the - * special '*' and '\' characters.
    Here is how the conversion - * algorithm works:

    - * - *
      - * - *
    • The '*' character is converted to MATCH_FILE, meaning that zero or - * more characters (excluding the path separator '/') are to be - * matched.
    • - * - *
    • The '**' sequence is converted to MATCH_PATH, meaning that zero or - * more characters (including the path separator '/') are to be - * matched.
    • - * - *
    • The '\' character is used as an escape sequence ('\*' is translated - * in '*', not in MATCH_FILE). If an exact '\' character is to be matched - * the source string must contain a '\\'. sequence.
    • - * - *
    - * - *

    When more than two '*' characters, not separated by another - * character, are found their value is considered as '**' (MATCH_PATH). - *
    The array is always terminated by a special value (MATCH_END). - *
    All MATCH* values are less than zero, while normal characters are - * equal or greater.

    - * - * @param data The string to translate. - * @return The encoded string as an int array, terminated by the MATCH_END - * value (don't consider the array length). - * @throws NullPointerException If data is null. - */ - public int[] compilePattern(String data) { - // Prepare the arrays - int[] expr = new int[data.length() + 2]; - char[] buff = data.toCharArray(); - - // Prepare variables for the translation loop - int y = 0; - boolean slash = false; - - // Must start from beginning - expr[y++] = MATCH_BEGIN; - - if (buff.length > 0) { - if (buff[0] == '\\') { - slash = true; - } else if (buff[0] == '*') { - expr[y++] = MATCH_FILE; - } else { - expr[y++] = buff[0]; - } - - // Main translation loop - for (int x = 1; x < buff.length; x++) { - // If the previous char was '\' simply copy this char. - if (slash) { - expr[y++] = buff[x]; - slash = false; - - // If the previous char was not '\' we have to do a bunch of - // checks - } else { - // If this char is '\' declare that and continue - if (buff[x] == '\\') { - slash = true; - - // If this char is '*' check the previous one - } else if (buff[x] == '*') { - // If the previous character als was '*' match a path - if (expr[y - 1] <= MATCH_FILE) { - expr[y - 1] = MATCH_PATH; - } else { - expr[y++] = MATCH_FILE; - } - } else { - expr[y++] = buff[x]; - } - } - } - } - - // Must match end at the end - expr[y] = MATCH_THEEND; - - return expr; - } - - /** - * Match a pattern agains a string and isolates wildcard replacement into - * a Stack. - * - * @param map The map to store matched values - * @param data The string to match - * @param expr The compiled wildcard expression - * @return True if a match - * @throws NullPointerException If any parameters are null - */ - public boolean match(Map map, String data, int[] expr) { - if (map == null) { - throw new NullPointerException("No map provided"); - } - - if (data == null) { - throw new NullPointerException("No data provided"); - } - - if (expr == null) { - throw new NullPointerException("No pattern expression provided"); - } - - char[] buff = data.toCharArray(); - - // Allocate the result buffer - char[] rslt = new char[expr.length + buff.length]; - - // The previous and current position of the expression character - // (MATCH_*) - int charpos = 0; - - // The position in the expression, input, translation and result arrays - int exprpos = 0; - int buffpos = 0; - int rsltpos = 0; - int offset = -1; - - // The matching count - int mcount = 0; - - // We want the complete data be in {0} - map.put(Integer.toString(mcount), data); - - // First check for MATCH_BEGIN - boolean matchBegin = false; - - if (expr[charpos] == MATCH_BEGIN) { - matchBegin = true; - exprpos = ++charpos; - } - - // Search the fist expression character (except MATCH_BEGIN - already - // skipped) - while (expr[charpos] >= 0) { - charpos++; - } - - // The expression charater (MATCH_*) - int exprchr = expr[charpos]; - - while (true) { - // Check if the data in the expression array before the current - // expression character matches the data in the input buffer - if (matchBegin) { - if (!matchArray(expr, exprpos, charpos, buff, buffpos)) { - return (false); - } - - matchBegin = false; - } else { - offset = indexOfArray(expr, exprpos, charpos, buff, buffpos); - - if (offset < 0) { - return (false); - } - } - - // Check for MATCH_BEGIN - if (matchBegin) { - if (offset != 0) { - return (false); - } - - matchBegin = false; - } - - // Advance buffpos - buffpos += (charpos - exprpos); - - // Check for END's - if (exprchr == MATCH_END) { - if (rsltpos > 0) { - map.put(Integer.toString(++mcount), - new String(rslt, 0, rsltpos)); - } - - // Don't care about rest of input buffer - return (true); - } else if (exprchr == MATCH_THEEND) { - if (rsltpos > 0) { - map.put(Integer.toString(++mcount), - new String(rslt, 0, rsltpos)); - } - - // Check that we reach buffer's end - return (buffpos == buff.length); - } - - // Search the next expression character - exprpos = ++charpos; - - while (expr[charpos] >= 0) { - charpos++; - } - - int prevchr = exprchr; - - exprchr = expr[charpos]; - - // We have here prevchr == * or **. - offset = - (prevchr == MATCH_FILE) - ? indexOfArray(expr, exprpos, charpos, buff, buffpos) - : lastIndexOfArray(expr, exprpos, charpos, buff, buffpos); - - if (offset < 0) { - return (false); - } - - // Copy the data from the source buffer into the result buffer - // to substitute the expression character - if (prevchr == MATCH_PATH) { - while (buffpos < offset) { - rslt[rsltpos++] = buff[buffpos++]; - } - } else { - // Matching file, don't copy '/' - while (buffpos < offset) { - if (buff[buffpos] == '/') { - return (false); - } - - rslt[rsltpos++] = buff[buffpos++]; - } - } - - map.put(Integer.toString(++mcount), new String(rslt, 0, rsltpos)); - rsltpos = 0; - } - } - - /** - * Get the offset of a part of an int array within a char array.
    This - * method return the index in d of the first occurrence after dpos of that - * part of array specified by r, starting at rpos and terminating at - * rend. - * - * @param r The array containing the data that need to be matched in - * d. - * @param rpos The index of the first character in r to look for. - * @param rend The index of the last character in r to look for plus 1. - * @param d The array of char that should contain a part of r. - * @param dpos The starting offset in d for the matching. - * @return The offset in d of the part of r matched in d or -1 if that was - * not found. - */ - protected int indexOfArray(int[] r, int rpos, int rend, char[] d, int dpos) { - // Check if pos and len are legal - if (rend < rpos) { - throw new IllegalArgumentException("rend < rpos"); - } - - // If we need to match a zero length string return current dpos - if (rend == rpos) { - return (d.length); //?? dpos? - } - - // If we need to match a 1 char length string do it simply - if ((rend - rpos) == 1) { - // Search for the specified character - for (int x = dpos; x < d.length; x++) { - if (r[rpos] == d[x]) { - return (x); - } - } - } - - // Main string matching loop. It gets executed if the characters to - // match are less then the characters left in the d buffer - while (((dpos + rend) - rpos) <= d.length) { - // Set current startpoint in d - int y = dpos; - - // Check every character in d for equity. If the string is matched - // return dpos - for (int x = rpos; x <= rend; x++) { - if (x == rend) { - return (dpos); - } - - if (r[x] != d[y++]) { - break; - } - } - - // Increase dpos to search for the same string at next offset - dpos++; - } - - // The remaining chars in d buffer were not enough or the string - // wasn't matched - return (-1); - } - - /** - * Get the offset of a last occurance of an int array within a char array. - *
    This method return the index in d of the last occurrence after - * dpos of that part of array specified by r, starting at rpos and - * terminating at rend. - * - * @param r The array containing the data that need to be matched in - * d. - * @param rpos The index of the first character in r to look for. - * @param rend The index of the last character in r to look for plus 1. - * @param d The array of char that should contain a part of r. - * @param dpos The starting offset in d for the matching. - * @return The offset in d of the last part of r matched in d or -1 if - * that was not found. - */ - protected int lastIndexOfArray(int[] r, int rpos, int rend, char[] d, - int dpos) { - // Check if pos and len are legal - if (rend < rpos) { - throw new IllegalArgumentException("rend < rpos"); - } - - // If we need to match a zero length string return current dpos - if (rend == rpos) { - return (d.length); //?? dpos? - } - - // If we need to match a 1 char length string do it simply - if ((rend - rpos) == 1) { - // Search for the specified character - for (int x = d.length - 1; x > dpos; x--) { - if (r[rpos] == d[x]) { - return (x); - } - } - } - - // Main string matching loop. It gets executed if the characters to - // match are less then the characters left in the d buffer - int l = d.length - (rend - rpos); - - while (l >= dpos) { - // Set current startpoint in d - int y = l; - - // Check every character in d for equity. If the string is matched - // return dpos - for (int x = rpos; x <= rend; x++) { - if (x == rend) { - return (l); - } - - if (r[x] != d[y++]) { - break; - } - } - - // Decrease l to search for the same string at next offset - l--; - } - - // The remaining chars in d buffer were not enough or the string - // wasn't matched - return (-1); - } - - /** - * Matches elements of array r from rpos to rend with array d, starting - * from dpos.
    This method return true if elements of array r from - * rpos to rend equals elements of array d starting from dpos to - * dpos+(rend-rpos). - * - * @param r The array containing the data that need to be matched in - * d. - * @param rpos The index of the first character in r to look for. - * @param rend The index of the last character in r to look for. - * @param d The array of char that should start from a part of r. - * @param dpos The starting offset in d for the matching. - * @return true if array d starts from portion of array r. - */ - protected boolean matchArray(int[] r, int rpos, int rend, char[] d, int dpos) { - if ((d.length - dpos) < (rend - rpos)) { - return (false); - } - - for (int i = rpos; i < rend; i++) { - if (r[i] != d[dpos++]) { - return (false); - } - } - - return (true); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/WildcardUtil.java b/core/src/main/java/com/opensymphony/xwork2/util/WildcardUtil.java deleted file mode 100644 index 8e6a573913..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/WildcardUtil.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2010 Yahoo, Inc. All rights reserved. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -import java.util.regex.Pattern; - -/** - * Helper class to convert wildcard expression to regular expression - */ -public class WildcardUtil { - - /** - * Convert wildcard pattern to Pattern - * @param pattern String containing wildcard pattern - * @return compiled regular expression as a Pattern - */ - public static Pattern compileWildcardPattern(String pattern) { - StringBuilder buf = new StringBuilder(pattern); - - for (int i=buf.length()-1; i>=0; i--) - { - char c = buf.charAt(i); - if (c == '*' && (i == 0 || buf.charAt(i-1) != '\\')) - { - buf.insert(i+1, '?'); - buf.insert(i, '.'); - } - else if (c == '*') - { - i--; // skip backslash, too - } - else if (needsBackslashToBeLiteralInRegex(c)) - { - buf.insert(i, '\\'); - } - } - - return Pattern.compile(buf.toString()); - } - - /** - * @param c character to test - * @return true if the given character must be escaped to be a literal - * inside a regular expression. - */ - - private static final String theSpecialRegexCharList = ".[]\\?*+{}|()^$"; - - public static boolean needsBackslashToBeLiteralInRegex( - char c) - { - return (theSpecialRegexCharList.indexOf(c) >= 0); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/XWorkTestCaseHelper.java b/core/src/main/java/com/opensymphony/xwork2/util/XWorkTestCaseHelper.java deleted file mode 100644 index 4d0183c484..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/XWorkTestCaseHelper.java +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.config.*; -import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider; -import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.ContainerBuilder; -import com.opensymphony.xwork2.util.location.LocatableProperties; - -/** - * Generic test setup methods to be used with any unit testing framework. - */ -public class XWorkTestCaseHelper { - - public static ConfigurationManager setUp() throws Exception { - ConfigurationManager configurationManager = new ConfigurationManager(Container.DEFAULT_NAME); - configurationManager.addContainerProvider(new XWorkConfigurationProvider()); - Configuration config = configurationManager.getConfiguration(); - Container container = config.getContainer(); - - // Reset the value stack - ValueStack stack = container.getInstance(ValueStackFactory.class).createValueStack(); - stack.getContext().put(ActionContext.CONTAINER, container); - ActionContext.setContext(new ActionContext(stack.getContext())); - - // clear out localization - //container.getInstance(LocalizedTextUtil.class).reset(); - - - //ObjectFactory.setObjectFactory(container.getInstance(ObjectFactory.class)); - return configurationManager; - } - - public static ConfigurationManager loadConfigurationProviders(ConfigurationManager configurationManager, - ConfigurationProvider... providers) { - try { - tearDown(configurationManager); - } catch (Exception e) { - throw new RuntimeException("Cannot clean old configuration", e); - } - configurationManager = new ConfigurationManager(Container.DEFAULT_NAME); - configurationManager.addContainerProvider(new ContainerProvider() { - public void destroy() {} - public void init(Configuration configuration) throws ConfigurationException {} - public boolean needsReload() { return false; } - - public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { - builder.setAllowDuplicates(true); - } - - }); - configurationManager.addContainerProvider(new XWorkConfigurationProvider()); - for (ConfigurationProvider prov : providers) { - if (prov instanceof XmlConfigurationProvider) { - ((XmlConfigurationProvider)prov).setThrowExceptionOnDuplicateBeans(false); - } - configurationManager.addContainerProvider(prov); - } - Container container = configurationManager.getConfiguration().getContainer(); - - // Reset the value stack - ValueStack stack = container.getInstance(ValueStackFactory.class).createValueStack(); - stack.getContext().put(ActionContext.CONTAINER, container); - ActionContext.setContext(new ActionContext(stack.getContext())); - - return configurationManager; - } - - public static void tearDown(ConfigurationManager configurationManager) throws Exception { - - // clear out configuration - if (configurationManager != null) { - configurationManager.destroyConfiguration(); - } - ActionContext.setContext(null); - } -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/util/classloader/AbstractResourceStore.java b/core/src/main/java/com/opensymphony/xwork2/util/classloader/AbstractResourceStore.java deleted file mode 100644 index 9166389193..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/classloader/AbstractResourceStore.java +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright 2002-2015 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.classloader; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.File; -import java.io.IOException; -import java.io.InputStream; - - -public abstract class AbstractResourceStore implements ResourceStore { - private static final Logger log = LogManager.getLogger(JarResourceStore.class); - protected final File file; - - public AbstractResourceStore(final File file) { - this.file = file; - } - - protected void closeQuietly(InputStream is) { - try { - if (is != null) { - is.close(); - } - } catch (IOException e) { - log.error("Unable to close file input stream", e); - } - } - - public void write(String pResourceName, byte[] pResourceData) { - } - - public String toString() { - return this.getClass().getName() + file.toString(); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/classloader/FileResourceStore.java b/core/src/main/java/com/opensymphony/xwork2/util/classloader/FileResourceStore.java deleted file mode 100644 index c2c79ea616..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/classloader/FileResourceStore.java +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.classloader; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.File; -import java.io.FileInputStream; - - -/** - * Reads a class from disk - * class taken from Apache JCI - */ -public final class FileResourceStore extends AbstractResourceStore { - private static final Logger LOG = LogManager.getLogger(FileResourceStore.class); - - public FileResourceStore(final File file) { - super(file); - } - - public byte[] read(final String pResourceName) { - FileInputStream fis = null; - try { - File file = getFile(pResourceName); - byte[] data = new byte[(int) file.length()]; - fis = new FileInputStream(file); - fis.read(data); - - return data; - } catch (Exception e) { - LOG.debug("Unable to read file [{}]", pResourceName, e); - return null; - } finally { - closeQuietly(fis); - } - } - - private File getFile(final String pResourceName) { - final String fileName = pResourceName.replace('/', File.separatorChar); - return new File(file, fileName); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/classloader/JarResourceStore.java b/core/src/main/java/com/opensymphony/xwork2/util/classloader/JarResourceStore.java deleted file mode 100644 index c5c1cc7c07..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/classloader/JarResourceStore.java +++ /dev/null @@ -1,66 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.util.classloader; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.*; -import java.util.zip.ZipEntry; -import java.util.zip.ZipFile; - -/** - * Read resources from a jar file - */ -public class JarResourceStore extends AbstractResourceStore { - private static final Logger LOG = LogManager.getLogger(JarResourceStore.class); - - public JarResourceStore(File file) { - super(file); - } - - public byte[] read(String pResourceName) { - InputStream in = null; - try { - ZipFile jarFile = new ZipFile(file); - ZipEntry entry = jarFile.getEntry(pResourceName); - - //read into byte array - ByteArrayOutputStream out = new ByteArrayOutputStream(); - in = jarFile.getInputStream(entry); - copy(in, out); - - return out.toByteArray(); - } catch (Exception e) { - LOG.debug("Unable to read file [{}] from [{}]", pResourceName, file.getName(), e); - return null; - } finally { - closeQuietly(in); - } - } - - public static long copy(InputStream input, OutputStream output) throws IOException { - byte[] buffer = new byte[1024 * 4]; - long count = 0; - int n = 0; - while (-1 != (n = input.read(buffer))) { - output.write(buffer, 0, n); - count += n; - } - return count; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/classloader/ResourceStore.java b/core/src/main/java/com/opensymphony/xwork2/util/classloader/ResourceStore.java deleted file mode 100644 index 80e6ce9588..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/classloader/ResourceStore.java +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.classloader; - -/** - * *interface taken from Apache JCI - */ -public interface ResourceStore { - - void write(final String pResourceName, final byte[] pResourceData); - - byte[] read(final String pResourceName); -} - diff --git a/core/src/main/java/com/opensymphony/xwork2/util/classloader/ResourceStoreClassLoader.java b/core/src/main/java/com/opensymphony/xwork2/util/classloader/ResourceStoreClassLoader.java deleted file mode 100644 index 8d4a6882b0..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/classloader/ResourceStoreClassLoader.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.classloader; - -/** - * class taken from Apache JCI - */ -public final class ResourceStoreClassLoader extends ClassLoader { - - private final ResourceStore[] stores; - - public ResourceStoreClassLoader(final ClassLoader pParent, final ResourceStore[] pStores) { - super(pParent); - - stores = new ResourceStore[pStores.length]; - System.arraycopy(pStores, 0, stores, 0, stores.length); - } - - private Class fastFindClass(final String name) { - - if (stores != null) { - String fileName = name.replace('.', '/') + ".class"; - for (final ResourceStore store : stores) { - final byte[] clazzBytes = store.read(fileName); - if (clazzBytes != null) { - definePackage(name); - return defineClass(name, clazzBytes, 0, clazzBytes.length); - } - } - } - - return null; - } - - protected synchronized Class loadClass(String name, boolean resolve) throws ClassNotFoundException { - Class clazz = findLoadedClass(name); - - if (clazz == null) { - clazz = fastFindClass(name); - - if (clazz == null) { - final ClassLoader parent = getParent(); - if (parent != null) { - clazz = parent.loadClass(name); - } else { - throw new ClassNotFoundException(name); - } - } - } - - if (resolve) { - resolveClass(clazz); - } - - return clazz; - } - - protected Class findClass(final String name) throws ClassNotFoundException { - final Class clazz = fastFindClass(name); - if (clazz == null) { - throw new ClassNotFoundException(name); - } - return clazz; - } - - /** - * Define the package information associated with a class. - * - * @param className the class name of for which the package information - * is to be determined. - */ - protected void definePackage(String className){ - int classIndex = className.lastIndexOf('.'); - if (classIndex == -1) { - return; - } - String packageName = className.substring(0, classIndex); - if (getPackage(packageName) != null) { - return; - } - definePackage(packageName, null, null, null, null, null, null, null); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinderFactory.java b/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinderFactory.java deleted file mode 100644 index 7998c3cfd3..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassFinderFactory.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2002-2003,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.finder; - -import java.net.URL; -import java.util.Collection; -import java.util.Set; - -/** - * Allows create different ClassFinders which should help support different Java versions - */ -public interface ClassFinderFactory { - - ClassFinder buildClassFinder(ClassLoaderInterface classLoaderInterface, Collection urls, boolean extractBaseInterfaces, Set protocols, Test classNameFilter); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassLoaderInterface.java b/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassLoaderInterface.java deleted file mode 100644 index f9b4a0fbcb..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassLoaderInterface.java +++ /dev/null @@ -1,41 +0,0 @@ -/* - * Copyright 2002-2003,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.finder; - -import java.net.URL; -import java.util.Enumeration; -import java.io.IOException; -import java.io.InputStream; - -/** - * Classes implementing this interface can find resources and load classes, usually delegating to a class - * loader - */ -public interface ClassLoaderInterface { - - //key used to add the current ClassLoaderInterface to ActionContext - public final String CLASS_LOADER_INTERFACE = "__current_class_loader_interface"; - - Class loadClass(String name) throws ClassNotFoundException; - - URL getResource(String name); - - public Enumeration getResources(String name) throws IOException; - - public InputStream getResourceAsStream(String name) throws IOException; - - ClassLoaderInterface getParent(); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassLoaderInterfaceDelegate.java b/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassLoaderInterfaceDelegate.java deleted file mode 100644 index 79fa46084d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/finder/ClassLoaderInterfaceDelegate.java +++ /dev/null @@ -1,52 +0,0 @@ -/* - * Copyright 2002-2003,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.finder; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.Enumeration; - -/** - * Default implementation of ClassLoaderInterface, which delegates to an actual ClassLoader - */ -public class ClassLoaderInterfaceDelegate implements ClassLoaderInterface { - private ClassLoader classLoader; - - public ClassLoaderInterfaceDelegate(ClassLoader classLoader) { - this.classLoader = classLoader; - } - - public Class loadClass(String name) throws ClassNotFoundException { - return classLoader.loadClass(name); - } - - public URL getResource(String className) { - return classLoader.getResource(className); - } - - public Enumeration getResources(String name) throws IOException { - return classLoader.getResources(name); - } - - public InputStream getResourceAsStream(String name) { - return classLoader.getResourceAsStream(name); - } - - public ClassLoaderInterface getParent() { - return classLoader.getParent() != null ? new ClassLoaderInterfaceDelegate(classLoader.getParent()) : null; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/finder/Test.java b/core/src/main/java/com/opensymphony/xwork2/util/finder/Test.java deleted file mode 100644 index b78d6f4b67..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/finder/Test.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2002-2003,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.finder; - -/** - * This is the testing interface that is used to accept or reject resources. - */ -public interface Test { - /** - * The test method. - * - * @param t The resource object to test. - * @return True if the resource should be accepted, false otherwise. - */ - public boolean test(T t); -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java deleted file mode 100644 index 55833ee14b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManager.java +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright 2002-2003,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.fs; - -import com.opensymphony.xwork2.FileManager; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.io.InputStream; -import java.net.MalformedURLException; -import java.net.URL; -import java.util.*; -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * Default implementation of {@link FileManager} - */ -public class DefaultFileManager implements FileManager { - - private static Logger LOG = LogManager.getLogger(DefaultFileManager.class); - - private static final Pattern JAR_PATTERN = Pattern.compile("^(jar:|wsjar:|zip:|vfsfile:|code-source:)?(file:)?(.*?)(\\!/|\\.jar/)(.*)"); - private static final int JAR_FILE_PATH = 3; - - protected static Map files = Collections.synchronizedMap(new HashMap()); - - protected boolean reloadingConfigs = false; - - public DefaultFileManager() { - } - - public void setReloadingConfigs(boolean reloadingConfigs) { - this.reloadingConfigs = reloadingConfigs; - } - - public boolean fileNeedsReloading(URL fileUrl) { - return fileUrl != null && fileNeedsReloading(fileUrl.toString()); - } - - public boolean fileNeedsReloading(String fileName) { - Revision revision = files.get(fileName); - if (revision == null) { - // no revision yet and we keep the revision history, so - // return whether the file needs to be loaded for the first time - return reloadingConfigs; - } - return revision.needsReloading(); - } - - public InputStream loadFile(URL fileUrl) { - if (fileUrl == null) { - return null; - } - InputStream is = openFile(fileUrl); - monitorFile(fileUrl); - return is; - } - - private InputStream openFile(URL fileUrl) { - try { - InputStream is = fileUrl.openStream(); - if (is == null) { - throw new IllegalArgumentException("No file '" + fileUrl + "' found as a resource"); - } - return is; - } catch (IOException e) { - throw new IllegalArgumentException("No file '" + fileUrl + "' found as a resource"); - } - } - - public void monitorFile(URL fileUrl) { - String fileName = fileUrl.toString(); - Revision revision; - LOG.debug("Creating revision for URL: {}", fileName); - if (isJarURL(fileUrl)) { - revision = JarEntryRevision.build(fileUrl, this); - } else { - revision = FileRevision.build(fileUrl); - } - if (revision == null) { - files.put(fileName, Revision.build(fileUrl)); - } else { - files.put(fileName, revision); - } - } - - /** - * Check if given URL is matching Jar pattern for different servers - * - * @param fileUrl jar file URL - * @return if given URL is matching Jar pattern for different servers - */ - protected boolean isJarURL(URL fileUrl) { - Matcher jarMatcher = JAR_PATTERN.matcher(fileUrl.getPath()); - return jarMatcher.matches(); - } - - public URL normalizeToFileProtocol(URL url) { - String fileName = url.toExternalForm(); - Matcher jarMatcher = JAR_PATTERN.matcher(fileName); - try { - if (jarMatcher.matches()) { - String path = jarMatcher.group(JAR_FILE_PATH); - return new URL("file", "", path); - } else if ("file".equals(url.getProtocol())) { - return url; // it's already a file - } else { - LOG.warn("Could not normalize URL [{}] to file protocol!", url); - return null; - } - } catch (MalformedURLException e) { - LOG.warn("Error normalizing URL [{}] to file protocol!", url, e); - return null; - } - } - - public boolean support() { - return false; // allow other implementation to be used first - } - - public boolean internal() { - return true; - } - - public Collection getAllPhysicalUrls(URL url) throws IOException { - return Arrays.asList(url); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManagerFactory.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManagerFactory.java deleted file mode 100644 index c19385fd17..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/fs/DefaultFileManagerFactory.java +++ /dev/null @@ -1,80 +0,0 @@ -package com.opensymphony.xwork2.util.fs; - -import com.opensymphony.xwork2.FileManager; -import com.opensymphony.xwork2.FileManagerFactory; -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.HashSet; -import java.util.Set; - -/** - * Default implementation - */ -public class DefaultFileManagerFactory implements FileManagerFactory { - - private static final Logger LOG = LogManager.getLogger(DefaultFileManagerFactory.class); - - private boolean reloadingConfigs; - private FileManager systemFileManager; - private Container container; - - @Inject(value = "system") - public void setFileManager(FileManager fileManager) { - this.systemFileManager = fileManager; - } - - @Inject - public void setContainer(Container container) { - this.container = container; - } - - @Inject(value = XWorkConstants.RELOAD_XML_CONFIGURATION, required = false) - public void setReloadingConfigs(String reloadingConfigs) { - this.reloadingConfigs = Boolean.parseBoolean(reloadingConfigs); - } - - public FileManager getFileManager() { - FileManager fileManager = lookupFileManager(); - if (fileManager != null) { - LOG.debug("Using FileManager implementation [{}]", fileManager.getClass().getSimpleName()); - fileManager.setReloadingConfigs(reloadingConfigs); - return fileManager; - } - LOG.debug("Using default implementation of FileManager provided under name [system]: {}", systemFileManager.getClass().getSimpleName()); - systemFileManager.setReloadingConfigs(reloadingConfigs); - return systemFileManager; - } - - private FileManager lookupFileManager() { - Set names = container.getInstanceNames(FileManager.class); - LOG.debug("Found following implementations of FileManager interface: {}", names); - Set internals = new HashSet<>(); - Set users = new HashSet<>(); - for (String fmName : names) { - FileManager fm = container.getInstance(FileManager.class, fmName); - if (fm.internal()) { - internals.add(fm); - } else { - users.add(fm); - } - } - for (FileManager fm : users) { - if (fm.support()) { - LOG.debug("Using FileManager implementation [{}]", fm.getClass().getSimpleName()); - return fm; - } - } - LOG.debug("No user defined FileManager, looking up for internal implementations!"); - for (FileManager fm : internals) { - if (fm.support()) { - return fm; - } - } - return null; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/FileRevision.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/FileRevision.java deleted file mode 100644 index f59d1d4e19..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/fs/FileRevision.java +++ /dev/null @@ -1,52 +0,0 @@ -package com.opensymphony.xwork2.util.fs; - -import java.io.File; -import java.net.URISyntaxException; -import java.net.URL; - -/** - * Represents file resource revision, used for file://* resources - */ -public class FileRevision extends Revision { - - private File file; - private long lastModified; - - public static Revision build(URL fileUrl) { - File file; - try { - if (fileUrl != null) { - file = new File(fileUrl.toURI()); - } else { - return null; - } - } catch (URISyntaxException e) { - file = new File(fileUrl.getPath()); - } catch (Throwable t) { - return null; - } - if (file.exists() && file.canRead()) { - long lastModified = file.lastModified(); - return new FileRevision(file, lastModified); - } - return null; - } - - private FileRevision(File file, long lastUpdated) { - if (file == null) { - throw new IllegalArgumentException("File cannot be null"); - } - - this.file = file; - this.lastModified = lastUpdated; - } - - public File getFile() { - return file; - } - - public boolean needsReloading() { - return this.lastModified < this.file.lastModified(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java deleted file mode 100644 index 4b962af08d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/fs/JarEntryRevision.java +++ /dev/null @@ -1,82 +0,0 @@ -package com.opensymphony.xwork2.util.fs; - -import com.opensymphony.xwork2.FileManager; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; -import org.apache.commons.io.FileUtils; - -import java.io.IOException; -import java.net.URL; -import java.util.jar.JarFile; -import java.util.zip.ZipEntry; - -/** - * Represents jar resource revision, used for jar://* resource - */ -public class JarEntryRevision extends Revision { - - private static Logger LOG = LogManager.getLogger(JarEntryRevision.class); - - private static final String JAR_FILE_NAME_SEPARATOR = "!/"; - private static final String JAR_FILE_EXTENSION_END = ".jar/"; - - private String jarFileName; - private String fileNameInJar; - private long lastModified; - - public static Revision build(URL fileUrl, FileManager fileManager) { - // File within a Jar - // Find separator index of jar filename and filename within jar - String jarFileName = ""; - try { - String fileName = fileUrl.toString(); - int separatorIndex = fileName.indexOf(JAR_FILE_NAME_SEPARATOR); - if (separatorIndex == -1) { - separatorIndex = fileName.lastIndexOf(JAR_FILE_EXTENSION_END); - } - if (separatorIndex == -1) { - LOG.warn("Could not find end of jar file!"); - return null; - } - - // Split file name - jarFileName = fileName.substring(0, separatorIndex); - int index = separatorIndex + JAR_FILE_NAME_SEPARATOR.length(); - String fileNameInJar = fileName.substring(index).replaceAll("%20", " "); - - URL url = fileManager.normalizeToFileProtocol(fileUrl); - if (url != null) { - JarFile jarFile = new JarFile(FileUtils.toFile(url)); - ZipEntry entry = jarFile.getEntry(fileNameInJar); - return new JarEntryRevision(jarFileName, fileNameInJar, entry.getTime()); - } else { - return null; - } - } catch (Throwable e) { - LOG.warn("Could not create JarEntryRevision for [{}]!", jarFileName, e); - return null; - } - } - - private JarEntryRevision(String jarFileName, String fileNameInJar, long lastModified) { - if ((jarFileName == null) || (fileNameInJar == null)) { - throw new IllegalArgumentException("JarFileName and FileNameInJar cannot be null"); - } - this.jarFileName = jarFileName; - this.fileNameInJar = fileNameInJar; - this.lastModified = lastModified; - } - - public boolean needsReloading() { - ZipEntry entry; - try { - JarFile jarFile = new JarFile(this.jarFileName); - entry = jarFile.getEntry(this.fileNameInJar); - } catch (IOException e) { - entry = null; - } - - return entry != null && (lastModified < entry.getTime()); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/fs/Revision.java b/core/src/main/java/com/opensymphony/xwork2/util/fs/Revision.java deleted file mode 100644 index 8da65fcd33..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/fs/Revision.java +++ /dev/null @@ -1,21 +0,0 @@ -package com.opensymphony.xwork2.util.fs; - -import java.net.URL; - -/** - * Class represents common revision resource, should be used as default class when no other option exists - */ -public class Revision { - - protected Revision() { - } - - public boolean needsReloading() { - return false; - } - - public static Revision build(URL fileUrl) { - return new Revision(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/location/Locatable.java b/core/src/main/java/com/opensymphony/xwork2/util/location/Locatable.java deleted file mode 100644 index fc6f69cd19..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/location/Locatable.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright 2005 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.location; - -/** - * A interface that should be implemented by objects knowning their location (i.e. where they - * have been created from). - */ -public interface Locatable { - /** - * Get the location of this object - * - * @return the location - */ - public Location getLocation(); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/location/LocatableProperties.java b/core/src/main/java/com/opensymphony/xwork2/util/location/LocatableProperties.java deleted file mode 100644 index 8df44f3c69..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/location/LocatableProperties.java +++ /dev/null @@ -1,81 +0,0 @@ -package com.opensymphony.xwork2.util.location; - -import com.opensymphony.xwork2.util.PropertiesReader; - -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.Reader; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; - -/** - * Properties implementation that remembers the location of each property. When - * loaded, a custom properties file parser is used to remember both the line number - * and preceeding comments for each property entry. - */ -public class LocatableProperties extends Properties implements Locatable { - - Location location; - Map propLocations; - - public LocatableProperties() { - this(Location.UNKNOWN); - } - - public LocatableProperties(Location loc) { - super(); - this.location = loc; - this.propLocations = new HashMap<>(); - } - - @Override - public void load(InputStream in) throws IOException { - Reader reader = new InputStreamReader(in); - PropertiesReader pr = new PropertiesReader(reader); - while (pr.nextProperty()) { - String name = pr.getPropertyName(); - String val = pr.getPropertyValue(); - int line = pr.getLineNumber(); - String desc = convertCommentsToString(pr.getCommentLines()); - - Location loc = new LocationImpl(desc, location.getURI(), line, 0); - setProperty(name, val, loc); - } - } - - String convertCommentsToString(List lines) { - StringBuilder sb = new StringBuilder(); - if (lines != null && !lines.isEmpty()) { - for (String line : lines) { - sb.append(line).append('\n'); - } - } - return sb.toString(); - } - - public Object setProperty(String key, String value, Object locationObj) { - Object obj = super.setProperty(key, value); - if (location != null) { - Location loc = LocationUtils.getLocation(locationObj); - propLocations.put(key, loc); - } - return obj; - } - - public Location getPropertyLocation(String key) { - Location loc = propLocations.get(key); - if (loc != null) { - return loc; - } else { - return Location.UNKNOWN; - } - } - - public Location getLocation() { - return location; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/location/Located.java b/core/src/main/java/com/opensymphony/xwork2/util/location/Located.java deleted file mode 100644 index 7c2c795ed8..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/location/Located.java +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright 2005 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.location; - -/** - * Base class for location aware objects - */ -public abstract class Located implements Locatable { - - protected Location location; - - /** - * Get the location of this object - * - * @return the location - */ - public Location getLocation() { - return location; - } - - /** - * Set the location of this object - * - * @param loc the location - */ - public void setLocation(Location loc) { - this.location = loc; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/location/Location.java b/core/src/main/java/com/opensymphony/xwork2/util/location/Location.java deleted file mode 100644 index 7791d4fd2d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/location/Location.java +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright 2005 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.location; - -import java.util.List; - - -/** - * A location in a resource. The location is composed of the URI of the resource, and - * the line and column numbers within that resource (when available), along with a description. - *

    - * Locations are mostly provided by {@link Locatable}s objects. - */ -public interface Location { - - /** - * Constant for unknown locations. - */ - public static final Location UNKNOWN = LocationImpl.UNKNOWN; - - /** - * Get the description of this location - * - * @return the description (can be null) - */ - String getDescription(); - - /** - * Get the URI of this location - * - * @return the URI (null if unknown). - */ - String getURI(); - - /** - * Get the line number of this location - * - * @return the line number (-1 if unknown) - */ - int getLineNumber(); - - /** - * Get the column number of this location - * - * @return the column number (-1 if unknown) - */ - int getColumnNumber(); - - /** - * Gets a source code snippet with the default padding - * - * @param padding The amount of lines before and after the error to include - * @return A list of source lines - */ - List getSnippet(int padding); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/location/package.html b/core/src/main/java/com/opensymphony/xwork2/util/location/package.html deleted file mode 100644 index 840814bd98..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/location/package.html +++ /dev/null @@ -1,3 +0,0 @@ - - Classes and utilities used to track location information. - \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/Logger.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/Logger.java deleted file mode 100644 index b16605505b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/Logger.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging; - -/** - * Main logger interface for logging things - * - * @deprecated since 2.5 - */ -@Deprecated -public interface Logger { - - void trace(String msg, String... args); - - void trace(String msg, Object... args); - - void trace(String msg, Throwable ex, String... args); - - boolean isTraceEnabled(); - - void debug(String msg, String... args); - - void debug(String msg, Object... args); - - void debug(String msg, Throwable ex, String... args); - - boolean isDebugEnabled(); - - void info(String msg, String... args); - - void info(String msg, Throwable ex, String... args); - - boolean isInfoEnabled(); - - void warn(String msg, String... args); - - void warn(String msg, Object... args); - - void warn(String msg, Throwable ex, String... args); - - boolean isWarnEnabled(); - - void error(String msg, String... args); - - void error(String msg, Object... args); - - void error(String msg, Throwable ex, String... args); - - boolean isErrorEnabled(); - - void fatal(String msg, String... args); - - void fatal(String msg, Throwable ex, String... args); - - boolean isFatalEnabled(); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/LoggerFactory.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/LoggerFactory.java deleted file mode 100644 index 79e7e59163..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/LoggerFactory.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging; - -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.XWorkException; -import com.opensymphony.xwork2.util.logging.commons.CommonsLoggerFactory; -import com.opensymphony.xwork2.util.logging.jdk.JdkLoggerFactory; -import com.opensymphony.xwork2.util.logging.log4j2.Log4j2LoggerFactory; -import com.opensymphony.xwork2.util.logging.slf4j.Slf4jLoggerFactory; - -import java.util.LinkedList; -import java.util.List; -import java.util.concurrent.locks.ReadWriteLock; -import java.util.concurrent.locks.ReentrantReadWriteLock; - -/** - * Creates loggers. Static accessor will lazily try to decide on the best factory if none specified. - * - * @deprecated since 2.5 - */ -@Deprecated -public abstract class LoggerFactory { - - private static final ReadWriteLock lock = new ReentrantReadWriteLock(); - private static LoggerFactory factory; - - private static final List loggers = new LinkedList(){ - { - add(new LoggerClass("org.apache.commons.logging.LogFactory", CommonsLoggerFactory.class)); - add(new LoggerClass("org.slf4j.LoggerFactory", Slf4jLoggerFactory.class)); - add(new LoggerClass("org.apache.logging.log4j.LogManager", Log4j2LoggerFactory.class)); - } - }; - - public static void setLoggerFactory(LoggerFactory factory) { - lock.writeLock().lock(); - try { - LoggerFactory.factory = factory; - } finally { - lock.writeLock().unlock(); - } - } - - public static Logger getLogger(Class cls) { - return getLoggerFactory().getLoggerImpl(cls); - } - - public static Logger getLogger(String name) { - return getLoggerFactory().getLoggerImpl(name); - } - - protected static LoggerFactory getLoggerFactory() { - lock.readLock().lock(); - try { - if (factory != null) { - return factory; - } - } finally { - lock.readLock().unlock(); - } - lock.writeLock().lock(); - try { - if (factory == null) { - createLoggerFactory(); - } - return factory; - } finally { - lock.writeLock().unlock(); - } - } - - private static void createLoggerFactory() { - String userLoggerFactory = System.getProperty(XWorkConstants.XWORK_LOGGER_FACTORY); - if (userLoggerFactory != null) { - try { - Class clazz = Class.forName(userLoggerFactory); - factory = (LoggerFactory) clazz.newInstance(); - } catch (Exception e) { - throw new XWorkException("System property [" + XWorkConstants.XWORK_LOGGER_FACTORY + - "] was defined as [" + userLoggerFactory + "] but there is a problem to use that LoggerFactory!", e); - } - } else { - factory = new JdkLoggerFactory(); - for (LoggerClass logger : loggers) { - if (logger.isSupported()) { - factory = logger.createInstance(); - break; - } - } - } - } - - protected abstract Logger getLoggerImpl(Class cls); - - protected abstract Logger getLoggerImpl(String name); - - private static class LoggerClass { - - private final String loggerClazzName; - private final Class loggerImplClazz; - - public LoggerClass(String loggerClazzName, Class loggerImplClazz) { - this.loggerClazzName = loggerClazzName; - this.loggerImplClazz = loggerImplClazz; - } - - public boolean isSupported() { - try { - Class.forName(loggerClazzName); - return true; - } catch (ClassNotFoundException ignore) { - return false; - } - } - - public LoggerFactory createInstance() { - try { - return loggerImplClazz.newInstance(); - } catch (Exception e) { - throw new XWorkException(e); - } - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/LoggerUtils.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/LoggerUtils.java deleted file mode 100644 index 47fe3396b5..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/LoggerUtils.java +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging; - -import java.util.LinkedList; -import java.util.List; - -/** - * Logging utility methods - * - * @deprecated since 2.5 - */ -@Deprecated -public class LoggerUtils { - - /** - * Formats messages using parameters. For example, the call: - * - *

    -     * format("foo #0 #1", "bob", "joe");
    -     * 
    - * - * will return: - *
    -     * foo bob joe
    -     * 
    - * - * @param msg The message - * @param args A list of arguments. A maximum of 10 are supported. - * @return The formatted string - */ - public static String format(String msg, String... args) { - if (msg != null && msg.length() > 0 && msg.indexOf('#') > -1) { - StringBuilder sb = new StringBuilder(); - boolean isArg = false; - for (int x = 0; x < msg.length(); x++) { - char c = msg.charAt(x); - if (isArg) { - isArg = false; - if (Character.isDigit(c)) { - int val = Character.getNumericValue(c); - if (val >= 0 && val < args.length) { - sb.append(args[val]); - continue; - } - } - sb.append('#'); - } - if (c == '#') { - isArg = true; - continue; - } - sb.append(c); - } - - if (isArg) { - sb.append('#'); - } - return sb.toString(); - } - return msg; - - } - - public static String format(String msg, Object[] args) { - List strArgs = new LinkedList(); - for (Object arg : args) { - strArgs.add(arg != null ? arg.toString() : "(null)"); - } - return format(msg, strArgs.toArray(new String[strArgs.size()])); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/commons/CommonsLogger.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/commons/CommonsLogger.java deleted file mode 100644 index ff96d5073c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/commons/CommonsLogger.java +++ /dev/null @@ -1,127 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging.commons; - -import com.opensymphony.xwork2.util.logging.Logger; -import com.opensymphony.xwork2.util.logging.LoggerUtils; -import org.apache.commons.logging.Log; - -/** - * Simple logger that delegates to commons logging - * - * @deprecated since 2.5 - */ -@Deprecated -public class CommonsLogger implements Logger { - - private Log log; - - public CommonsLogger(Log log) { - this.log = log; - } - - public void error(String msg, String... args) { - log.error(LoggerUtils.format(msg, args)); - } - - public void error(String msg, Object... args) { - log.error(LoggerUtils.format(msg, args)); - } - - public void error(String msg, Throwable ex, String... args) { - log.error(LoggerUtils.format(msg, args), ex); - } - - public void info(String msg, String... args) { - log.info(LoggerUtils.format(msg, args)); - } - - public void info(String msg, Throwable ex, String... args) { - log.info(LoggerUtils.format(msg, args), ex); - } - - - - public boolean isInfoEnabled() { - return log.isInfoEnabled(); - } - - public void warn(String msg, String... args) { - log.warn(LoggerUtils.format(msg, args)); - } - - public void warn(String msg, Object... args) { - log.warn(LoggerUtils.format(msg, args)); - } - - public void warn(String msg, Throwable ex, String... args) { - log.warn(LoggerUtils.format(msg, args), ex); - } - - public boolean isDebugEnabled() { - return log.isDebugEnabled(); - } - - public void debug(String msg, String... args) { - log.debug(LoggerUtils.format(msg, args)); - } - - public void debug(String msg, Object... args) { - log.debug(LoggerUtils.format(msg, args)); - } - - public void debug(String msg, Throwable ex, String... args) { - log.debug(LoggerUtils.format(msg, args), ex); - } - - public boolean isTraceEnabled() { - return log.isTraceEnabled(); - } - - public void trace(String msg, String... args) { - log.trace(LoggerUtils.format(msg, args)); - } - - public void trace(String msg, Object... args) { - log.trace(LoggerUtils.format(msg, args)); - } - - public void trace(String msg, Throwable ex, String... args) { - log.trace(LoggerUtils.format(msg, args), ex); - } - - - public void fatal(String msg, String... args) { - log.fatal(LoggerUtils.format(msg, args)); - } - - public void fatal(String msg, Throwable ex, String... args) { - log.fatal(LoggerUtils.format(msg, args), ex); - } - - public boolean isErrorEnabled() { - return log.isErrorEnabled(); - } - - public boolean isFatalEnabled() { - return log.isFatalEnabled(); - } - - public boolean isWarnEnabled() { - return log.isWarnEnabled(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/commons/CommonsLoggerFactory.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/commons/CommonsLoggerFactory.java deleted file mode 100644 index 06e39b1b97..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/commons/CommonsLoggerFactory.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging.commons; - -import com.opensymphony.xwork2.util.logging.Logger; -import com.opensymphony.xwork2.util.logging.LoggerFactory; -import org.apache.commons.logging.LogFactory; - -/** - * Creates commons-logging-backed loggers - * - * @deprecated since 2.5 - */ -@Deprecated -public class CommonsLoggerFactory extends LoggerFactory { - - @Override - protected Logger getLoggerImpl(Class cls) { - return new CommonsLogger(LogFactory.getLog(cls)); - } - - @Override - protected Logger getLoggerImpl(String name) { - return new CommonsLogger(LogFactory.getLog(name)); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/jdk/JdkLogger.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/jdk/JdkLogger.java deleted file mode 100644 index acab3a82e7..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/jdk/JdkLogger.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging.jdk; - -import com.opensymphony.xwork2.util.logging.Logger; -import com.opensymphony.xwork2.util.logging.LoggerUtils; - -import java.util.logging.Level; - -/** - * Delegates to jdk logger. Maps fatal to Level.SEVERE along with error. - * - * @deprecated since 2.5 - */ -@Deprecated -public class JdkLogger implements Logger { - - private java.util.logging.Logger log; - - public JdkLogger(java.util.logging.Logger log) { - this.log = log; - } - - public void error(String msg, String... args) { - log.log(Level.SEVERE, LoggerUtils.format(msg, args)); - } - - public void error(String msg, Object... args) { - log.log(Level.SEVERE, LoggerUtils.format(msg, args)); - } - - public void error(String msg, Throwable ex, String... args) { - log.log(Level.SEVERE, LoggerUtils.format(msg, args), ex); - } - - public void fatal(String msg, String... args) { - log.log(Level.SEVERE, LoggerUtils.format(msg, args)); - } - - public void fatal(String msg, Throwable ex, String... args) { - log.log(Level.SEVERE, LoggerUtils.format(msg, args), ex); - } - - public void info(String msg, String... args) { - log.log(Level.INFO, LoggerUtils.format(msg, args)); - } - - public void info(String msg, Throwable ex, String... args) { - log.log(Level.INFO, LoggerUtils.format(msg, args), ex); - } - - public boolean isInfoEnabled() { - return log.isLoggable(Level.INFO); - } - - public void warn(String msg, String... args) { - log.log(Level.WARNING, LoggerUtils.format(msg, args)); - } - - public void warn(String msg, Object... args) { - log.log(Level.WARNING, LoggerUtils.format(msg, args)); - } - - public void warn(String msg, Throwable ex, String... args) { - log.log(Level.WARNING, LoggerUtils.format(msg, args), ex); - } - - public boolean isDebugEnabled() { - return log.isLoggable(Level.FINE); - } - - public void debug(String msg, String... args) { - log.log(Level.FINE, LoggerUtils.format(msg, args)); - } - - public void debug(String msg, Object... args) { - log.log(Level.FINE, LoggerUtils.format(msg, args)); - } - - public void debug(String msg, Throwable ex, String... args) { - log.log(Level.FINE, LoggerUtils.format(msg, args), ex); - } - - public boolean isTraceEnabled() { - return log.isLoggable(Level.FINEST); - } - - public void trace(String msg, String... args) { - log.log(Level.FINEST, LoggerUtils.format(msg, args)); - } - - public void trace(String msg, Object... args) { - log.log(Level.FINEST, LoggerUtils.format(msg, args)); - } - - public void trace(String msg, Throwable ex, String... args) { - log.log(Level.FINEST, LoggerUtils.format(msg, args), ex); - } - - public boolean isErrorEnabled() { - return log.isLoggable(Level.SEVERE); - } - - public boolean isFatalEnabled() { - return log.isLoggable(Level.SEVERE); - } - - public boolean isWarnEnabled() { - return log.isLoggable(Level.WARNING); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/jdk/JdkLoggerFactory.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/jdk/JdkLoggerFactory.java deleted file mode 100644 index 268ccce55d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/jdk/JdkLoggerFactory.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging.jdk; - -import com.opensymphony.xwork2.util.logging.Logger; -import com.opensymphony.xwork2.util.logging.LoggerFactory; - -/** - * Creates jdk loggers - * - * @deprecated since 2.5 - */ -@Deprecated -public class JdkLoggerFactory extends LoggerFactory { - - @Override - protected Logger getLoggerImpl(Class cls) { - return new JdkLogger(java.util.logging.Logger.getLogger(cls.getName())); - } - - @Override - protected Logger getLoggerImpl(String name) { - return new JdkLogger(java.util.logging.Logger.getLogger(name)); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/log4j2/Log4j2Logger.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/log4j2/Log4j2Logger.java deleted file mode 100644 index 1e0cda5bb6..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/log4j2/Log4j2Logger.java +++ /dev/null @@ -1,124 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging.log4j2; - -import com.opensymphony.xwork2.util.logging.Logger; -import com.opensymphony.xwork2.util.logging.LoggerUtils; - -/** - * Simple logger that delegates to log4j2 logging - * - * @deprecated since 2.5 - */ -@Deprecated -public class Log4j2Logger implements Logger { - - private org.apache.logging.log4j.Logger log; - - public Log4j2Logger(org.apache.logging.log4j.Logger log) { - this.log = log; - } - - public void error(String msg, String... args) { - log.error(LoggerUtils.format(msg, args)); - } - - public void error(String msg, Object... args) { - log.error(LoggerUtils.format(msg, args)); - } - - public void error(String msg, Throwable ex, String... args) { - log.error(LoggerUtils.format(msg, args), ex); - } - - public void info(String msg, String... args) { - log.info(LoggerUtils.format(msg, args)); - } - - public void info(String msg, Throwable ex, String... args) { - log.info(LoggerUtils.format(msg, args), ex); - } - - public boolean isInfoEnabled() { - return log.isInfoEnabled(); - } - - public void warn(String msg, String... args) { - log.warn(LoggerUtils.format(msg, args)); - } - - public void warn(String msg, Object... args) { - log.warn(LoggerUtils.format(msg, args)); - } - - public void warn(String msg, Throwable ex, String... args) { - log.warn(LoggerUtils.format(msg, args), ex); - } - - public boolean isDebugEnabled() { - return log.isDebugEnabled(); - } - - public void debug(String msg, String... args) { - log.debug(LoggerUtils.format(msg, args)); - } - - public void debug(String msg, Object... args) { - log.debug(LoggerUtils.format(msg, args)); - } - - public void debug(String msg, Throwable ex, String... args) { - log.debug(LoggerUtils.format(msg, args), ex); - } - - public boolean isTraceEnabled() { - return log.isTraceEnabled(); - } - - public void trace(String msg, String... args) { - log.trace(LoggerUtils.format(msg, args)); - } - - public void trace(String msg, Object... args) { - log.trace(LoggerUtils.format(msg, args)); - } - - public void trace(String msg, Throwable ex, String... args) { - log.trace(LoggerUtils.format(msg, args), ex); - } - - - public void fatal(String msg, String... args) { - log.fatal(LoggerUtils.format(msg, args)); - } - - public void fatal(String msg, Throwable ex, String... args) { - log.fatal(LoggerUtils.format(msg, args), ex); - } - - public boolean isErrorEnabled() { - return log.isErrorEnabled(); - } - - public boolean isFatalEnabled() { - return log.isFatalEnabled(); - } - - public boolean isWarnEnabled() { - return log.isWarnEnabled(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/log4j2/Log4j2LoggerFactory.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/log4j2/Log4j2LoggerFactory.java deleted file mode 100644 index 04cae8034d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/log4j2/Log4j2LoggerFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging.log4j2; - -import com.opensymphony.xwork2.util.logging.Logger; -import com.opensymphony.xwork2.util.logging.LoggerFactory; - -/** - * Creates log4j2-logging-backed loggers - * - * You can use the same to explicit tell the framework which implementation to use and don't depend on class discovery: - *
    - *   -Dxwork.loggerFactory=com.opensymphony.xwork2.util.logging.log4j2.Log4j2LoggerFactory
    - * 
    - * - * @deprecated since 2.5 - */ -@Deprecated -public class Log4j2LoggerFactory extends LoggerFactory { - - @Override - protected Logger getLoggerImpl(Class cls) { - return new Log4j2Logger(org.apache.logging.log4j.LogManager.getLogger(cls)); - } - - @Override - protected Logger getLoggerImpl(String name) { - return new Log4j2Logger(org.apache.logging.log4j.LogManager.getLogger(name)); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/slf4j/Slf4jLogger.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/slf4j/Slf4jLogger.java deleted file mode 100644 index 4dea191617..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/slf4j/Slf4jLogger.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging.slf4j; - -import com.opensymphony.xwork2.util.logging.Logger; -import com.opensymphony.xwork2.util.logging.LoggerUtils; - -/** - * Simple logger that delegates to slf4j logging - * - * @deprecated since 2.5 - */ -@Deprecated -public class Slf4jLogger implements Logger { - - private org.slf4j.Logger log; - - public Slf4jLogger(org.slf4j.Logger log) { - this.log = log; - } - - public void error(String msg, String... args) { - log.error(LoggerUtils.format(msg, args)); - } - - public void error(String msg, Object... args) { - log.error(LoggerUtils.format(msg, args)); - } - - public void error(String msg, Throwable ex, String... args) { - log.error(LoggerUtils.format(msg, args), ex); - } - - public void info(String msg, String... args) { - log.info(LoggerUtils.format(msg, args)); - } - - public void info(String msg, Throwable ex, String... args) { - log.info(LoggerUtils.format(msg, args), ex); - } - - public boolean isInfoEnabled() { - return log.isInfoEnabled(); - } - - public void warn(String msg, String... args) { - log.warn(LoggerUtils.format(msg, args)); - } - - public void warn(String msg, Object... args) { - log.warn(LoggerUtils.format(msg, args)); - } - - public void warn(String msg, Throwable ex, String... args) { - log.warn(LoggerUtils.format(msg, args), ex); - } - - public boolean isDebugEnabled() { - return log.isDebugEnabled(); - } - - public void debug(String msg, String... args) { - log.debug(LoggerUtils.format(msg, args)); - } - - public void debug(String msg, Object... args) { - log.debug(LoggerUtils.format(msg, args)); - } - - public void debug(String msg, Throwable ex, String... args) { - log.debug(LoggerUtils.format(msg, args), ex); - } - - public boolean isTraceEnabled() { - return log.isTraceEnabled(); - } - - public void trace(String msg, String... args) { - log.trace(LoggerUtils.format(msg, args)); - } - - public void trace(String msg, Object... args) { - log.trace(LoggerUtils.format(msg, args)); - } - - public void trace(String msg, Throwable ex, String... args) { - log.trace(LoggerUtils.format(msg, args), ex); - } - - - public void fatal(String msg, String... args) { - log.error(LoggerUtils.format(msg, args)); - } - - public void fatal(String msg, Throwable ex, String... args) { - log.error(LoggerUtils.format(msg, args), ex); - } - - public boolean isErrorEnabled() { - return log.isErrorEnabled(); - } - - /** Fatal is not support by Slf4j */ - public boolean isFatalEnabled() { - return log.isErrorEnabled(); - } - - public boolean isWarnEnabled() { - return log.isWarnEnabled(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/logging/slf4j/Slf4jLoggerFactory.java b/core/src/main/java/com/opensymphony/xwork2/util/logging/slf4j/Slf4jLoggerFactory.java deleted file mode 100644 index aba7d8647b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/logging/slf4j/Slf4jLoggerFactory.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.util.logging.slf4j; - -import com.opensymphony.xwork2.util.logging.Logger; -import com.opensymphony.xwork2.util.logging.LoggerFactory; - -/** - * Creates slf4j-logging-backed loggers - * - * You can use the same to explicit tell the framework which implementation to use and don't depend on class discovery: - *
    - *   -Dxwork.loggerFactory=com.opensymphony.xwork2.util.logging.slf4j.Slf4jLoggerFactory
    - * 
    - * - * @deprecated since 2.5 - */ -@Deprecated -public class Slf4jLoggerFactory extends LoggerFactory { - - @Override - protected Logger getLoggerImpl(Class cls) { - return new Slf4jLogger(org.slf4j.LoggerFactory.getLogger(cls)); - } - - @Override - protected Logger getLoggerImpl(String name) { - return new Slf4jLogger(org.slf4j.LoggerFactory.getLogger(name)); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/package.html b/core/src/main/java/com/opensymphony/xwork2/util/package.html deleted file mode 100644 index e400bf97ff..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/package.html +++ /dev/null @@ -1 +0,0 @@ -XWork util classes. diff --git a/core/src/main/java/com/opensymphony/xwork2/util/profiling/ObjectProfiler.java b/core/src/main/java/com/opensymphony/xwork2/util/profiling/ObjectProfiler.java deleted file mode 100644 index 733bce3ccd..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/profiling/ObjectProfiler.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * Copyright (c) 2002-2003, Atlassian Software Systems Pty Ltd All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * Neither the name of Atlassian Software Systems Pty Ltd nor the names of - * its contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.opensymphony.xwork2.util.profiling; - -import java.lang.reflect.InvocationHandler; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Proxy; - -/** - * @author Scott Farquhar - */ -public class ObjectProfiler { - - /** - *

    - * Given a class, and an interface that it implements, return a proxied version of the class that implements - * the interface. - *

    - * - *

    - * The usual use of this is to profile methods from Factory objects: - *

    - * - *
    -     * public PersistenceManager getPersistenceManager()
    -     * {
    -     *   return new DefaultPersistenceManager();
    -     * }
    -     *
    -     * instead write:
    -     * public PersistenceManager getPersistenceManager()
    -     * {
    -     *   return ObjectProfiler.getProfiledObject(PersistenceManager.class, new DefaultPersistenceManager());
    -     * }
    -     * 
    - * - *

    - * A side effect of this is that you will no longer be able to downcast to DefaultPersistenceManager. This is probably a *good* thing. - *

    - * - * @param interfaceClazz The interface to implement. - * @param o The object to proxy - * @return A proxied object, or the input object if the interfaceClazz wasn't an interface. - */ - public static Object getProfiledObject(Class interfaceClazz, Object o) { - //if we are not active - then do nothing - if (!UtilTimerStack.isActive()) { - return o; - } - - //this should always be true - you shouldn't be passing something that isn't an interface - if (interfaceClazz.isInterface()) { - InvocationHandler timerHandler = new TimerInvocationHandler(o); - return Proxy.newProxyInstance(interfaceClazz.getClassLoader(), - new Class[]{interfaceClazz}, timerHandler); - } else { - return o; - } - } - - /** - * A profiled call {@link Method#invoke(java.lang.Object, java.lang.Object[])}. If {@link UtilTimerStack#isActive() } - * returns false, then no profiling is performed. - * - * @param target target method - * @param value value - * @param args arguments - * - * @return target object - * - * @throws IllegalAccessException in case of access errors - * @throws InvocationTargetException in case of invocation errors - */ - public static Object profiledInvoke(Method target, Object value, Object[] args) throws IllegalAccessException, InvocationTargetException { - //if we are not active - then do nothing - if (!UtilTimerStack.isActive()) { - return target.invoke(value, args); - } - - String logLine = getTrimmedClassName(target) + "." + target.getName() + "()"; - - UtilTimerStack.push(logLine); - try { - Object returnValue = target.invoke(value, args); - - //if the return value is an interface then we should also proxy it! - if (returnValue != null && target.getReturnType().isInterface()) { - InvocationHandler timerHandler = new TimerInvocationHandler(returnValue); - return Proxy.newProxyInstance(returnValue.getClass().getClassLoader(), - new Class[]{target.getReturnType()}, timerHandler); - } else { - return returnValue; - } - } finally { - UtilTimerStack.pop(logLine); - } - } - - /** - * Given a method, get the Method name, with no package information. - * - * @param method method - * - * @return method name, with no package information - */ - public static String getTrimmedClassName(Method method) { - String classname = method.getDeclaringClass().getName(); - return classname.substring(classname.lastIndexOf('.') + 1); - } - -} - -class TimerInvocationHandler implements InvocationHandler { - protected Object target; - - public TimerInvocationHandler(Object target) { - if (target == null) { - throw new IllegalArgumentException("Target Object passed to timer cannot be null"); - } - this.target = target; - } - - public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { - return ObjectProfiler.profiledInvoke(method, target, args); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/profiling/ProfilingTimerBean.java b/core/src/main/java/com/opensymphony/xwork2/util/profiling/ProfilingTimerBean.java deleted file mode 100644 index b94f0abaf5..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/profiling/ProfilingTimerBean.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2002-2003, Atlassian Software Systems Pty Ltd All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * Neither the name of Atlassian Software Systems Pty Ltd nor the names of - * its contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.opensymphony.xwork2.util.profiling; - -import java.util.ArrayList; -import java.util.List; - -/** - * Bean to contain information about the pages profiled - * - * @author Mike Cannon-Brookes - * @author Scott Farquhar - * @version $Date$ $Id$ - */ -public class ProfilingTimerBean implements java.io.Serializable { - - private static final long serialVersionUID = -6180672043920208784L; - - List children = new ArrayList<>(); - ProfilingTimerBean parent = null; - - String resource; - - long startTime; - long totalTime; - - public ProfilingTimerBean(String resource) { - this.resource = resource; - } - - protected void addParent(ProfilingTimerBean parent) { - this.parent = parent; - } - - public ProfilingTimerBean getParent() { - return parent; - } - - - public void addChild(ProfilingTimerBean child) { - children.add(child); - child.addParent(this); - } - - - public void setStartTime() { - this.startTime = System.currentTimeMillis(); - } - - public void setEndTime() { - this.totalTime = System.currentTimeMillis() - startTime; - } - - public String getResource() { - return resource; - } - - /** - * @param minTime minimum time - * @return a formatted string representing all the methods that took longer than a specified time. - */ - public String getPrintable(long minTime) { - return getPrintable("", minTime); - } - - protected String getPrintable(String indent, long minTime) { - //only print the value if we are larger or equal to the min time. - if (totalTime >= minTime) { - StringBuilder buffer = new StringBuilder(); - buffer.append(indent); - buffer.append("[" + totalTime + "ms] - " + resource); - buffer.append("\n"); - - for (ProfilingTimerBean aChildren : children) { - buffer.append((aChildren).getPrintable(indent + " ", minTime)); - } - - return buffer.toString(); - } else - return ""; - } -} - diff --git a/core/src/main/java/com/opensymphony/xwork2/util/profiling/UtilTimerStack.java b/core/src/main/java/com/opensymphony/xwork2/util/profiling/UtilTimerStack.java deleted file mode 100644 index 092cb8d9a6..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/profiling/UtilTimerStack.java +++ /dev/null @@ -1,470 +0,0 @@ -/* - * Copyright (c) 2002-2003, Atlassian Software Systems Pty Ltd All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * - * * Redistributions of source code must retain the above copyright notice, - * this list of conditions and the following disclaimer. - * * Redistributions in binary form must reproduce the above copyright notice, - * this list of conditions and the following disclaimer in the documentation and/or - * other materials provided with the distribution. - * * Neither the name of Atlassian Software Systems Pty Ltd nor the names of - * its contributors may be used to endorse or promote products derived from this - * software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE - * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR - * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES - * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; - * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON - * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT - * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS - * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. - */ -package com.opensymphony.xwork2.util.profiling; - -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - - -/** - *

    A timer stack.

    - * - *

    - * Struts2 profiling aspects involves the following: - *

    - * - *
      - *
    • ActionContextCleanUp
    • - *
    • FreemarkerPageFilter
    • - *
    • DispatcherFilter - *
        - *
      • Dispatcher - *
          - *
        • creation of DefaultActionProxy - *
            - *
          • creation of DefaultActionInvocation - *
              - *
            • creation of Action
            • - *
            - *
          • - *
          - *
        • - *
        • execution of DefaultActionProxy - *
            - *
          • invocation of DefaultActionInvocation - *
              - *
            • invocation of Interceptors
            • - *
            • invocation of Action
            • - *
            • invocation of PreResultListener
            • - *
            • invocation of Result
            • - *
            - *
          • - *
          - *
        • - *
        - *
      • - *
      - *
    • - *
    - * - * - * - * - * - *

    - * XWork2 profiling aspects involves the following: - *

    - * - *
      - *
    • creation of DefaultActionProxy - *
        - *
      • creation of DefaultActionInvocation
      • - *
      - *
    • - *
    • creation of Action
    • - *
    • execution of DefaultActionProxy - *
        - *
      • invocation of DefaultActionInvocation - *
          - *
        • invocation of Interceptors
        • - *
        • invocation of Action
        • - *
        • invocation of PreResultListener
        • - *
        • invocation of Result
        • - *
        - *
      • - *
      - *
    • - *
    - * - * - * - * - * - *

    - * Activating / Deactivating of the profiling feature could be done through: - *

    - * - * - * - * - *

    System properties:

    - *
    - * 
    - *
    - *  -Dxwork.profile.activate=true
    - *
    - * 
    - * 
    - * - * - *

    - * This could be done in the container startup script eg. CATALINA_OPTS in catalina.sh - * (tomcat) or using 'java -Dxwork.profile.activate=true -jar start.jar' (jetty) - *

    - * - * - * - *

    Code :

    - *
    - * 
    - *
    - *  UtilTimerStack.setActivate(true);
    - *
    - * 
    - * 
    - * - *

    - * This could be done in a static block, in a Spring bean with lazy-init='false', - * in a Servlet with init-on-startup as some numeric value, in a Filter or - * Listener's init method etc. - *

    - * - * - *

    - * Parameter: - *

    - * - *
    - * 
    - *
    - * <action ... >
    - *  ...
    - *  <interceptor-ref name="profiling">
    - *      <param name="profilingKey">profiling</param>
    - *  </interceptor-ref>
    - *  ...
    - * </action>
    - *
    - * or
    - *
    - * <action .... >
    - * ...
    - *  <interceptor-ref name="profiling" />
    - * ...
    - * </action>
    - *
    - * through url
    - *
    - * http://host:port/context/namespace/someAction.action?profiling=true
    - *
    - * through code
    - *
    - * ActionContext.getContext().getParameters().put("profiling", "true);
    - *
    - * 
    - * 
    - * - * - * - *

    - * To use profiling activation through parameter, one will need to pass in through - * the 'profiling' parameter (which is the default) and could be changed through - * the param tag in the interceptor-ref. - *

    - * - * - *

    Warning:

    - * - * - *

    - * Profiling activation through a parameter requires the following: - *

    - * - *
      - *
    • Profiling interceptor in interceptor stack
    • - *
    • dev mode on (struts.devMode=true in struts.properties) - *
    - * - * - * - * - *

    - * One could filter out the profile logging by having a System property as follows. With this - * 'xwork.profile.mintime' property, one could only log profile information when its execution time - * exceed those specified in 'xwork.profile.mintime' system property. If no such property is specified, - * it will be assumed to be 0, hence all profile information will be logged. - *

    - * - * - * - *
    - * 
    - *
    - *  -Dxwork.profile.mintime=10000
    - *
    - * 
    - * 
    - * - * - *

    - * One could extend the profiling feature provided by Struts2 in their web application as well. - *

    - * - * - *
    - * 
    - *
    - *    String logMessage = "Log message";
    - *    UtilTimerStack.push(logMessage);
    - *    try {
    - *        // do some code
    - *    }
    - *    finally {
    - *        UtilTimerStack.pop(logMessage); // this needs to be the same text as above
    - *    }
    - *
    - * 
    - * 
    - *

    - * or - *

    - *
    - * 
    - *
    - *   String result = UtilTimerStack.profile("purchaseItem: ",
    - *       new UtilTimerStack.ProfilingBlock<String>() {
    - *            public String doProfiling() {
    - *               // do some code
    - *               return "Ok";
    - *            }
    - *       });
    - *
    - * 
    - * 
    - * - * - * - *

    - * Profiled result is logged using commons-logging under the logger named - * 'com.opensymphony.xwork2.util.profiling.UtilTimerStack'. Depending on the underlying logging implementation - * say if it is Log4j, one could direct the log to appear in a different file, being emailed to someone or have - * it stored in the db. - *

    - * - * - */ -public class UtilTimerStack { - - // A reference to the current ProfilingTimerBean - protected static ThreadLocal current = new ThreadLocal<>(); - - /** - * System property that controls whether this timer should be used or not. Set to "true" activates - * the timer. Set to "false" to deactivate. - */ - public static final String ACTIVATE_PROPERTY = "xwork.profile.activate"; - - /** - * System property that controls the min time, that if exceeded will cause a log (at INFO level) to be - * created. - */ - public static final String MIN_TIME = "xwork.profile.mintime"; - - private static final Logger LOG = LogManager.getLogger(UtilTimerStack.class); - - /** - * Initialized in a static block, it can be changed at runtime by calling setActive(...) - */ - private static boolean active; - - static { - active = "true".equalsIgnoreCase(System.getProperty(ACTIVATE_PROPERTY)); - } - - /** - * Create and start a performance profiling with the name given. Deal with - * profile hierarchy automatically, so caller don't have to be concern about it. - * - * @param name profile name - */ - public static void push(String name) { - if (!isActive()) { - return; - } - - //create a new timer and start it - ProfilingTimerBean newTimer = new ProfilingTimerBean(name); - newTimer.setStartTime(); - - //if there is a current timer - add the new timer as a child of it - ProfilingTimerBean currentTimer = (ProfilingTimerBean) current.get(); - if (currentTimer != null) { - currentTimer.addChild(newTimer); - } - - //set the new timer to be the current timer - current.set(newTimer); - } - - /** - * End a performance profiling with the name given. Deal with - * profile hierarchy automatically, so caller don't have to be concern about it. - * - * @param name profile name - */ - public static void pop(String name) { - if (!isActive()) { - return; - } - - ProfilingTimerBean currentTimer = current.get(); - - //if the timers are matched up with each other (ie push("a"); pop("a")); - if (currentTimer != null && name != null && name.equals(currentTimer.getResource())) { - currentTimer.setEndTime(); - ProfilingTimerBean parent = currentTimer.getParent(); - //if we are the root timer, then print out the times - if (parent == null) { - printTimes(currentTimer); - current.set(null); //for those servers that use thread pooling - } else { - current.set(parent); - } - } else { - //if timers are not matched up, then print what we have, and then print warning. - if (currentTimer != null) { - printTimes(currentTimer); - current.set(null); //prevent printing multiple times - LOG.warn("Unmatched Timer. Was expecting {}, instead got {}", currentTimer.getResource(), name); - } - } - } - - /** - * Do a log (at INFO level) of the time taken for this particular profiling. - * - * @param currentTimer profiling timer bean - */ - private static void printTimes(ProfilingTimerBean currentTimer) { - LOG.info(currentTimer.getPrintable(getMinTime())); - } - - /** - * Get the min time for this profiling, it searches for a System property - * 'xwork.profile.mintime' and default to 0. - * - * @return min time for this profiling - */ - private static long getMinTime() { - try { - return Long.parseLong(System.getProperty(MIN_TIME, "0")); - } catch (NumberFormatException e) { - return -1; - } - } - - /** - * Determine if profiling is being activated, by searching for a system property - * 'xwork.profile.activate', default to false (profiling is off). - * - * @return true, if active, false otherwise. - */ - public static boolean isActive() { - return active; - } - - /** - * @param active Turn profiling on or off. - */ - public static void setActive(boolean active) { - if (active) { - System.setProperty(ACTIVATE_PROPERTY, "true"); - } else { - System.clearProperty(ACTIVATE_PROPERTY); - } - UtilTimerStack.active = active; - } - - - /** - *

    - * A convenience method that allows block of code subjected to profiling to be executed - * and avoid the need of coding boiler code that does pushing (UtilTimeBean.push(...)) and - * poping (UtilTimerBean.pop(...)) in a try ... finally ... block. - *

    - * - *

    - * Example of usage: - *

    - * - *
    -     * 	 // we need a returning result
    -     *   String result = UtilTimerStack.profile("purchaseItem: ",
    -     *       new UtilTimerStack.ProfilingBlock<String>() {
    -     *            public String doProfiling() {
    -     *               getMyService().purchaseItem(....)
    -     *               return "Ok";
    -     *            }
    -     *       });
    -     * 
    - * - * or - * - *
    -     *   // we don't need a returning result
    -     *   UtilTimerStack.profile("purchaseItem: ",
    -     *       new UtilTimerStack.ProfilingBlock<String>() {
    -     *            public String doProfiling() {
    -     *               getMyService().purchaseItem(....)
    -     *               return null;
    -     *            }
    -     *       });
    -     * 
    - * - * @param any return value if there's one. - * @param name profile name - * @param block code block subjected to profiling - * @return T - * @throws Exception in case of any errors - */ - public static T profile(String name, ProfilingBlock block) throws Exception { - UtilTimerStack.push(name); - try { - return block.doProfiling(); - } finally { - UtilTimerStack.pop(name); - } - } - - /** - * A callback interface where code subjected to profile is to be executed. This eliminates the need - * of coding boiler code that does pushing (UtilTimerBean.push(...)) and poping (UtilTimerBean.pop(...)) - * in a try ... finally ... block. - * - * @param type - */ - public static interface ProfilingBlock { - - /** - * Method that execute the code subjected to profiling. - * - * @return profiles Type - * @throws Exception in case of any errors - */ - T doProfiling() throws Exception; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/profiling/package.html b/core/src/main/java/com/opensymphony/xwork2/util/profiling/package.html deleted file mode 100644 index c0b1f7f63c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/profiling/package.html +++ /dev/null @@ -1 +0,0 @@ -Classes to enable profiling of action execution. diff --git a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionContextFactory.java b/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionContextFactory.java deleted file mode 100644 index 704b5af71b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionContextFactory.java +++ /dev/null @@ -1,15 +0,0 @@ -package com.opensymphony.xwork2.util.reflection; - -import java.util.Map; - -public interface ReflectionContextFactory { - /** - * Creates and returns a new standard naming context for evaluating an OGNL - * expression. - * - * @param root the root of the object graph - * @return a new Map with the keys root and context - * set appropriately - */ - Map createDefaultContext( Object root ); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionContextState.java b/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionContextState.java deleted file mode 100644 index 9534ebc302..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionContextState.java +++ /dev/null @@ -1,177 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.util.reflection; - -import com.opensymphony.xwork2.conversion.impl.XWorkConverter; - -import java.util.HashMap; -import java.util.Map; - -/** - * Manages variables in the reflection context and returns values - * to be used by the application. - * - * @author Gabe - */ -public class ReflectionContextState { - - private static final String GETTING_BY_KEY_PROPERTY = "xwork.getting.by.key.property"; - private static final String SET_MAP_KEY = "set.map.key"; - - public static final String CURRENT_PROPERTY_PATH="current.property.path"; - public static final String FULL_PROPERTY_PATH="current.property.path"; - public static final String CREATE_NULL_OBJECTS = "xwork.NullHandler.createNullObjects"; - public static final String DENY_METHOD_EXECUTION = "xwork.MethodAccessor.denyMethodExecution"; - public static final String DENY_INDEXED_ACCESS_EXECUTION = "xwork.IndexedPropertyAccessor.denyMethodExecution"; - - public static boolean isCreatingNullObjects(Map context) { - //TODO - return getBooleanProperty(ReflectionContextState.CREATE_NULL_OBJECTS, context); - } - - public static void setCreatingNullObjects(Map context, boolean creatingNullObjects) { - setBooleanValue(ReflectionContextState.CREATE_NULL_OBJECTS, context, creatingNullObjects); - } - - public static boolean isGettingByKeyProperty(Map context) { - return getBooleanProperty(GETTING_BY_KEY_PROPERTY, context); - } - - public static void setDenyMethodExecution(Map context, boolean denyMethodExecution) { - setBooleanValue(ReflectionContextState.DENY_METHOD_EXECUTION, context, denyMethodExecution); - } - - public static boolean isDenyMethodExecution(Map context) { - return getBooleanProperty(ReflectionContextState.DENY_METHOD_EXECUTION, context); - } - - public static void setGettingByKeyProperty(Map context, boolean gettingByKeyProperty) { - setBooleanValue(GETTING_BY_KEY_PROPERTY, context, gettingByKeyProperty); - } - - public static boolean isReportingConversionErrors(Map context) { - return getBooleanProperty(XWorkConverter.REPORT_CONVERSION_ERRORS, context); - } - - public static void setReportingConversionErrors(Map context, boolean reportingErrors) { - setBooleanValue(XWorkConverter.REPORT_CONVERSION_ERRORS, context, reportingErrors); - } - - public static Class getLastBeanClassAccessed(Map context) { - return (Class)context.get(XWorkConverter.LAST_BEAN_CLASS_ACCESSED); - } - - public static void setLastBeanPropertyAccessed(Map context, String property) { - context.put(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED, property); - } - - public static String getLastBeanPropertyAccessed(Map context) { - return (String)context.get(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED); - } - - public static void setLastBeanClassAccessed(Map context, Class clazz) { - context.put(XWorkConverter.LAST_BEAN_CLASS_ACCESSED, clazz); - } - /** - *

    - * Gets the current property path but not completely. - * It does not use the [ and ] used in some representations - * of Maps and Lists. The reason for this is that the current - * property path is only currently used for caching purposes - * so there is no real reason to have an exact replica. - *

    - * - *

    So if the real path is myProp.myMap['myKey'] this would - * return myProp.myMap.myKey. - *

    - * - * @param context context map - * @return current property path - */ - public static String getCurrentPropertyPath(Map context) { - return (String)context.get(CURRENT_PROPERTY_PATH); - } - - public static String getFullPropertyPath(Map context) { - return (String)context.get(FULL_PROPERTY_PATH); - } - - public static void setFullPropertyPath(Map context, String path) { - context.put(FULL_PROPERTY_PATH, path); - - } - - public static void updateCurrentPropertyPath(Map context, Object name) { - String currentPath=getCurrentPropertyPath(context); - if (name!=null) { - if (currentPath!=null) { - StringBuilder sb = new StringBuilder(currentPath); - sb.append("."); - sb.append(name.toString()); - currentPath = sb.toString(); - } else { - currentPath = name.toString(); - } - context.put(CURRENT_PROPERTY_PATH, currentPath); - } - } - - public static void setSetMap(Map context, Map setMap, String path) { - Map> mapOfSetMaps=(Map)context.get(SET_MAP_KEY); - if (mapOfSetMaps==null) { - mapOfSetMaps = new HashMap<>(); - context.put(SET_MAP_KEY, mapOfSetMaps); - } - mapOfSetMaps.put(path, setMap); - } - - public static Map getSetMap(Map context, String path) { - Map> mapOfSetMaps=(Map)context.get(SET_MAP_KEY); - if (mapOfSetMaps==null) { - return null; - } - return mapOfSetMaps.get(path); - } - - private static boolean getBooleanProperty(String property, Map context) { - Boolean myBool=(Boolean)context.get(property); - return (myBool==null)?false:myBool.booleanValue(); - } - - private static void setBooleanValue(String property, Map context, boolean value) { - context.put(property, new Boolean(value)); - } - - /** - *@param context the context map - */ - public static void clearCurrentPropertyPath(Map context) { - context.put(CURRENT_PROPERTY_PATH, null); - - } - - public static void clear(Map context) { - if (context != null) { - context.put(XWorkConverter.LAST_BEAN_CLASS_ACCESSED,null); - context.put(XWorkConverter.LAST_BEAN_PROPERTY_ACCESSED,null); - - context.put(CURRENT_PROPERTY_PATH,null); - context.put(FULL_PROPERTY_PATH,null); - } - - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionException.java b/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionException.java deleted file mode 100644 index a6d107d9bb..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionException.java +++ /dev/null @@ -1,41 +0,0 @@ -package com.opensymphony.xwork2.util.reflection; - -import com.opensymphony.xwork2.XWorkException; - -public class ReflectionException extends XWorkException { - - public ReflectionException() { - // TODO Auto-generated constructor stub - } - - public ReflectionException(String s) { - super(s); - // TODO Auto-generated constructor stub - } - - public ReflectionException(String s, Object target) { - super(s, target); - // TODO Auto-generated constructor stub - } - - public ReflectionException(Throwable cause) { - super(cause); - // TODO Auto-generated constructor stub - } - - public ReflectionException(Throwable cause, Object target) { - super(cause, target); - // TODO Auto-generated constructor stub - } - - public ReflectionException(String s, Throwable cause) { - super(s, cause); - // TODO Auto-generated constructor stub - } - - public ReflectionException(String s, Throwable cause, Object target) { - super(s, cause, target); - // TODO Auto-generated constructor stub - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionExceptionHandler.java b/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionExceptionHandler.java deleted file mode 100644 index b5c7d8a5d6..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionExceptionHandler.java +++ /dev/null @@ -1,14 +0,0 @@ -package com.opensymphony.xwork2.util.reflection; - -/** - * Declares a class that wants to handle its own reflection exceptions - */ -public interface ReflectionExceptionHandler { - - /** - * Handles a reflection exception - * - * @param ex The reflection exception - */ - void handle(ReflectionException ex); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionProviderFactory.java b/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionProviderFactory.java deleted file mode 100644 index a05b7d6065..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/util/reflection/ReflectionProviderFactory.java +++ /dev/null @@ -1,10 +0,0 @@ -package com.opensymphony.xwork2.util.reflection; - -import com.opensymphony.xwork2.ActionContext; - -public class ReflectionProviderFactory { - - public static ReflectionProvider getInstance() { - return ActionContext.getContext().getContainer().getInstance(ReflectionProvider.class); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/ActionValidatorManager.java b/core/src/main/java/com/opensymphony/xwork2/validator/ActionValidatorManager.java deleted file mode 100644 index 6650817cc3..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/ActionValidatorManager.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator; - -import java.util.List; - -/** - * ActionValidatorManager is the main interface for validation managers (regular and annotation based). - * - * @author Rainer Hermanns - */ -public interface ActionValidatorManager { - - /** - * Returns a list of validators for the given class, context, and method. This is the primary - * lookup method for validators. - * - * @param clazz the class to lookup. - * @param context the context of the action class - can be null. - * @param method the name of the method being invoked on the action - can be null. - * @return a list of all validators for the given class and context. - */ - List getValidators(Class clazz, String context, String method); - - /** - * Returns a list of validators for the given class and context. This is the primary - * lookup method for validators. - * - * @param clazz the class to lookup. - * @param context the context of the action class - can be null. - * @return a list of all validators for the given class and context. - */ - List getValidators(Class clazz, String context); - - /** - * Validates the given object using action and its context. - * - * @param object the action to validate. - * @param context the action's context. - * @throws ValidationException if an error happens when validating the action. - */ - void validate(Object object, String context) throws ValidationException; - - /** - * Validates an action give its context and a validation context. - * - * @param object the action to validate. - * @param context the action's context. - * @param validatorContext the validation context to use - * @throws ValidationException if an error happens when validating the action. - */ - void validate(Object object, String context, ValidatorContext validatorContext) throws ValidationException; - - /** - * Validates the given object using an action, its context, and the name of the method being invoked on the action. - * - * @param object the action to validate. - * @param context the action's context. - * @param method the name of the method being invoked on the action - can be null. - * @throws ValidationException if an error happens when validating the action. - */ - void validate(Object object, String context, String method) throws ValidationException; - - /** - * Validates an action give its context and a validation context. - * - * @param object the action to validate. - * @param context the action's context. - * @param validatorContext the validation context to use - * @param method the name of the method being invoked on the action - can be null. - * @throws ValidationException if an error happens when validating the action. - */ - void validate(Object object, String context, ValidatorContext validatorContext, String method) throws ValidationException; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/AnnotationActionValidatorManager.java b/core/src/main/java/com/opensymphony/xwork2/validator/AnnotationActionValidatorManager.java deleted file mode 100644 index cd6fa4e857..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/AnnotationActionValidatorManager.java +++ /dev/null @@ -1,391 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator; - - -import com.opensymphony.xwork2.*; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ClassLoaderUtil; -import com.opensymphony.xwork2.util.ValueStack; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.*; - -/** - * AnnotationActionValidatorManager is the entry point into XWork's annotations-based validator framework. - * Validation rules are specified as annotations within the source files. - * - * @author Rainer Hermanns - * @author jepjep - */ -public class AnnotationActionValidatorManager implements ActionValidatorManager { - - /** - * The file suffix for any validation file. - */ - protected static final String VALIDATION_CONFIG_SUFFIX = "-validation.xml"; - - private final Map> validatorCache = Collections.synchronizedMap(new HashMap>()); - private final Map> validatorFileCache = Collections.synchronizedMap(new HashMap>()); - private static final Logger LOG = LogManager.getLogger(AnnotationActionValidatorManager.class); - - private ValidatorFactory validatorFactory; - private ValidatorFileParser validatorFileParser; - private FileManager fileManager; - private boolean reloadingConfigs; - private TextProviderFactory textProviderFactory; - - @Inject - public void setValidatorFactory(ValidatorFactory fac) { - this.validatorFactory = fac; - } - - @Inject - public void setValidatorFileParser(ValidatorFileParser parser) { - this.validatorFileParser = parser; - } - - @Inject - public void setFileManagerFactory(FileManagerFactory fileManagerFactory) { - this.fileManager = fileManagerFactory.getFileManager(); - } - - @Inject(value = XWorkConstants.RELOAD_XML_CONFIGURATION, required = false) - public void setReloadingConfigs(String reloadingConfigs) { - this.reloadingConfigs = Boolean.parseBoolean(reloadingConfigs); - } - - @Inject - public void setTextProviderFactory(TextProviderFactory textProviderFactory) { - this.textProviderFactory = textProviderFactory; - } - - public List getValidators(Class clazz, String context) { - return getValidators(clazz, context, null); - } - - public List getValidators(Class clazz, String context, String method) { - final String validatorKey = buildValidatorKey(clazz, context); - final List cfgs; - - if (validatorCache.containsKey(validatorKey)) { - if (reloadingConfigs) { - validatorCache.put(validatorKey, buildValidatorConfigs(clazz, context, true, null)); - } - } else { - validatorCache.put(validatorKey, buildValidatorConfigs(clazz, context, false, null)); - } - - // get the set of validator configs - cfgs = new ArrayList(validatorCache.get(validatorKey)); - - ValueStack stack = ActionContext.getContext().getValueStack(); - - // create clean instances of the validators for the caller's use - ArrayList validators = new ArrayList<>(cfgs.size()); - for (ValidatorConfig cfg : cfgs) { - if (method == null || method.equals(cfg.getParams().get("methodName"))) { - Validator validator = validatorFactory.getValidator( - new ValidatorConfig.Builder(cfg) - .removeParam("methodName") - .build()); - validator.setValidatorType(cfg.getType()); - validator.setValueStack(stack); - validators.add(validator); - } - } - - return validators; - } - - public void validate(Object object, String context) throws ValidationException { - validate(object, context, (String) null); - } - - public void validate(Object object, String context, String method) throws ValidationException { - ValidatorContext validatorContext = new DelegatingValidatorContext(object, textProviderFactory); - validate(object, context, validatorContext, method); - } - - public void validate(Object object, String context, ValidatorContext validatorContext) throws ValidationException { - validate(object, context, validatorContext, null); - } - - public void validate(Object object, String context, ValidatorContext validatorContext, String method) throws ValidationException { - List validators = getValidators(object.getClass(), context, method); - Set shortcircuitedFields = null; - - for (final Validator validator : validators) { - try { - validator.setValidatorContext(validatorContext); - - LOG.debug("Running validator: {} for object {} and method {}", validator, object, method); - - FieldValidator fValidator = null; - String fullFieldName = null; - - if (validator instanceof FieldValidator) { - fValidator = (FieldValidator) validator; - fullFieldName = fValidator.getValidatorContext().getFullFieldName(fValidator.getFieldName()); - - if ((shortcircuitedFields != null) && shortcircuitedFields.contains(fullFieldName)) { - LOG.debug("Short-circuited, skipping"); - continue; - } - } - - if (validator instanceof ShortCircuitableValidator && ((ShortCircuitableValidator) validator).isShortCircuit()) { - // get number of existing errors - List errs = null; - - if (fValidator != null) { - if (validatorContext.hasFieldErrors()) { - Collection fieldErrors = validatorContext.getFieldErrors().get(fullFieldName); - - if (fieldErrors != null) { - errs = new ArrayList<>(fieldErrors); - } - } - } else if (validatorContext.hasActionErrors()) { - Collection actionErrors = validatorContext.getActionErrors(); - - if (actionErrors != null) { - errs = new ArrayList<>(actionErrors); - } - } - - validator.validate(object); - - if (fValidator != null) { - if (validatorContext.hasFieldErrors()) { - Collection errCol = validatorContext.getFieldErrors().get(fullFieldName); - - if ((errCol != null) && !errCol.equals(errs)) { - LOG.debug("Short-circuiting on field validation"); - - if (shortcircuitedFields == null) { - shortcircuitedFields = new TreeSet(); - } - - shortcircuitedFields.add(fullFieldName); - } - } - } else if (validatorContext.hasActionErrors()) { - Collection errCol = validatorContext.getActionErrors(); - - if ((errCol != null) && !errCol.equals(errs)) { - LOG.debug("Short-circuiting"); - break; - } - } - - continue; - } - - validator.validate(object); - } finally { - validator.setValidatorContext(null); - } - - } - } - - /** - * Builds a key for validators - used when caching validators. - * - * @param clazz the action. - * @param context context - * @return a validator key which is the class name plus context. - */ - protected String buildValidatorKey(Class clazz, String context) { - ActionInvocation invocation = ActionContext.getContext().getActionInvocation(); - ActionProxy proxy = invocation.getProxy(); - ActionConfig config = proxy.getConfig(); - - StringBuilder sb = new StringBuilder(clazz.getName()); - sb.append("/"); - if (StringUtils.isNotBlank(config.getPackageName())) { - sb.append(config.getPackageName()); - sb.append("/"); - } - - // the key needs to use the name of the action from the config file, - // instead of the url, so wild card actions will have the same validator - // see WW-2996 - - // UPDATE: - // WW-3753 Using the config name instead of the context only for - // wild card actions to keep the flexibility provided - // by the original design (such as mapping different contexts - // to the same action and method if desired) - - // UPDATE: - // WW-4536 Using NameVariablePatternMatcher allows defines actions - // with patterns enclosed with '{}', it's similar case to WW-3753 - String configName = config.getName(); - if (configName.contains(ActionConfig.WILDCARD) || (configName.contains("{") && configName.contains("}"))) { - sb.append(configName); - sb.append("|"); - sb.append(proxy.getMethod()); - } else { - sb.append(context); - } - - return sb.toString(); - } - - private List buildAliasValidatorConfigs(Class aClass, String context, boolean checkFile) { - String fileName = aClass.getName().replace('.', '/') + "-" + context.replace('/', '-') + VALIDATION_CONFIG_SUFFIX; - - return loadFile(fileName, aClass, checkFile); - } - - - protected List buildClassValidatorConfigs(Class aClass, boolean checkFile) { - - String fileName = aClass.getName().replace('.', '/') + VALIDATION_CONFIG_SUFFIX; - - List result = new ArrayList<>(loadFile(fileName, aClass, checkFile)); - - AnnotationValidationConfigurationBuilder builder = new AnnotationValidationConfigurationBuilder(validatorFactory); - - List annotationResult = new ArrayList<>(builder.buildAnnotationClassValidatorConfigs(aClass)); - - result.addAll(annotationResult); - - return result; - - } - - /** - *

    This method 'collects' all the validator configurations for a given - * action invocation.

    - * - *

    It will traverse up the class hierarchy looking for validators for every super class - * and directly implemented interface of the current action, as well as adding validators for - * any alias of this invocation. Nifty!

    - * - *

    Given the following class structure:

    - *
    -     *   interface Thing;
    -     *   interface Animal extends Thing;
    -     *   interface Quadraped extends Animal;
    -     *   class AnimalImpl implements Animal;
    -     *   class QuadrapedImpl extends AnimalImpl implements Quadraped;
    -     *   class Dog extends QuadrapedImpl;
    -     * 
    - * - *

    This method will look for the following config files for Dog:

    - *
    -     *   Animal
    -     *   Animal-context
    -     *   AnimalImpl
    -     *   AnimalImpl-context
    -     *   Quadraped
    -     *   Quadraped-context
    -     *   QuadrapedImpl
    -     *   QuadrapedImpl-context
    -     *   Dog
    -     *   Dog-context
    -     * 
    - * - *

    Note that the validation rules for Thing is never looked for because no class in the - * hierarchy directly implements Thing.

    - * - * @param clazz the Class to look up validators for. - * @param context the context to use when looking up validators. - * @param checkFile true if the validation config file should be checked to see if it has been - * updated. - * @param checked the set of previously checked class-contexts, null if none have been checked - * @return a list of validator configs for the given class and context. - */ - private List buildValidatorConfigs(Class clazz, String context, boolean checkFile, Set checked) { - List validatorConfigs = new ArrayList<>(); - - if (checked == null) { - checked = new TreeSet<>(); - } else if (checked.contains(clazz.getName())) { - return validatorConfigs; - } - - if (clazz.isInterface()) { - Class[] interfaces = clazz.getInterfaces(); - - for (Class anInterface : interfaces) { - validatorConfigs.addAll(buildValidatorConfigs(anInterface, context, checkFile, checked)); - } - } else { - if (!clazz.equals(Object.class)) { - validatorConfigs.addAll(buildValidatorConfigs(clazz.getSuperclass(), context, checkFile, checked)); - } - } - - // look for validators for implemented interfaces - Class[] interfaces = clazz.getInterfaces(); - - for (Class anInterface1 : interfaces) { - if (checked.contains(anInterface1.getName())) { - continue; - } - - validatorConfigs.addAll(buildClassValidatorConfigs(anInterface1, checkFile)); - - if (context != null) { - validatorConfigs.addAll(buildAliasValidatorConfigs(anInterface1, context, checkFile)); - } - - checked.add(anInterface1.getName()); - } - - validatorConfigs.addAll(buildClassValidatorConfigs(clazz, checkFile)); - - if (context != null) { - validatorConfigs.addAll(buildAliasValidatorConfigs(clazz, context, checkFile)); - } - - checked.add(clazz.getName()); - - return validatorConfigs; - } - - private List loadFile(String fileName, Class clazz, boolean checkFile) { - List retList = Collections.emptyList(); - - URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz); - - if ((checkFile && fileManager.fileNeedsReloading(fileUrl)) || !validatorFileCache.containsKey(fileName)) { - try (InputStream is = fileManager.loadFile(fileUrl)) { - if (is != null) { - retList = new ArrayList<>(validatorFileParser.parseActionValidatorConfigs(validatorFactory, is, fileName)); - } - } catch (IOException e) { - LOG.error("Caught exception while loading file {}", fileName, e); - } - - validatorFileCache.put(fileName, retList); - } else { - retList = validatorFileCache.get(fileName); - } - - return retList; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/DefaultActionValidatorManager.java b/core/src/main/java/com/opensymphony/xwork2/validator/DefaultActionValidatorManager.java deleted file mode 100644 index 48d552a010..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/DefaultActionValidatorManager.java +++ /dev/null @@ -1,348 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.FileManager; -import com.opensymphony.xwork2.FileManagerFactory; -import com.opensymphony.xwork2.TextProviderFactory; -import com.opensymphony.xwork2.XWorkConstants; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ClassLoaderUtil; -import com.opensymphony.xwork2.util.ValueStack; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.IOException; -import java.io.InputStream; -import java.net.URL; -import java.util.*; - - -/** - *

    - * This is the entry point into XWork's rule-based validation framework. - *

    - * - *

    - * Validation rules are specified in XML configuration files named className-contextName-validation.xml where - * className is the name of the class the configuration is for and -contextName is optional - * (contextName is an arbitrary key that is used to look up additional validation rules for a - * specific context). - *

    - * - * @author Jason Carreira - * @author Mark Woon - * @author James House - * @author Rainer Hermanns - */ -public class DefaultActionValidatorManager implements ActionValidatorManager { - - private final static Logger LOG = LogManager.getLogger(DefaultActionValidatorManager.class); - - /** The file suffix for any validation file. */ - protected static final String VALIDATION_CONFIG_SUFFIX = "-validation.xml"; - - private final Map> validatorCache = Collections.synchronizedMap(new HashMap>()); - private final Map> validatorFileCache = Collections.synchronizedMap(new HashMap>()); - - private ValidatorFactory validatorFactory; - private ValidatorFileParser validatorFileParser; - private FileManager fileManager; - private boolean reloadingConfigs; - private TextProviderFactory textProviderFactory; - - @Inject - public void setValidatorFileParser(ValidatorFileParser parser) { - this.validatorFileParser = parser; - } - - @Inject - public void setValidatorFactory(ValidatorFactory fac) { - this.validatorFactory = fac; - } - - @Inject - public void setFileManagerFactory(FileManagerFactory fileManagerFactory) { - this.fileManager = fileManagerFactory.getFileManager(); - } - - @Inject(value = XWorkConstants.RELOAD_XML_CONFIGURATION, required = false) - public void setReloadingConfigs(String reloadingConfigs) { - this.reloadingConfigs = Boolean.parseBoolean(reloadingConfigs); - } - - @Inject - public void setTextProviderFactory(TextProviderFactory textProviderFactory) { - this.textProviderFactory = textProviderFactory; - } - - public synchronized List getValidators(Class clazz, String context) { - return getValidators(clazz, context, null); - } - - public synchronized List getValidators(Class clazz, String context, String method) { - final String validatorKey = buildValidatorKey(clazz, context); - - if (validatorCache.containsKey(validatorKey)) { - if (reloadingConfigs) { - validatorCache.put(validatorKey, buildValidatorConfigs(clazz, context, true, null)); - } - } else { - validatorCache.put(validatorKey, buildValidatorConfigs(clazz, context, false, null)); - } - ValueStack stack = ActionContext.getContext().getValueStack(); - - // get the set of validator configs - List cfgs = validatorCache.get(validatorKey); - - // create clean instances of the validators for the caller's use - ArrayList validators = new ArrayList<>(cfgs.size()); - for (ValidatorConfig cfg : cfgs) { - if (method == null || method.equals(cfg.getParams().get("methodName"))) { - Validator validator = validatorFactory.getValidator(cfg); - validator.setValidatorType(cfg.getType()); - validator.setValueStack(stack); - validators.add(validator); - } - } - return validators; - } - - public void validate(Object object, String context) throws ValidationException { - validate(object, context, (String) null); - } - - public void validate(Object object, String context, String method) throws ValidationException { - ValidatorContext validatorContext = new DelegatingValidatorContext(object, textProviderFactory); - validate(object, context, validatorContext, method); - } - - public void validate(Object object, String context, ValidatorContext validatorContext) throws ValidationException { - validate(object, context, validatorContext, null); - } - - public void validate(Object object, String context, ValidatorContext validatorContext, String method) throws ValidationException { - List validators = getValidators(object.getClass(), context, method); - Set shortcircuitedFields = null; - - for (final Validator validator : validators) { - try { - validator.setValidatorContext(validatorContext); - - LOG.debug("Running validator: {} for object {} and method {}", validator, object, method); - - FieldValidator fValidator = null; - String fullFieldName = null; - - if (validator instanceof FieldValidator) { - fValidator = (FieldValidator) validator; - fullFieldName = fValidator.getValidatorContext().getFullFieldName(fValidator.getFieldName()); - - if ((shortcircuitedFields != null) && shortcircuitedFields.contains(fullFieldName)) { - LOG.debug("Short-circuited, skipping"); - continue; - } - } - - if (validator instanceof ShortCircuitableValidator && ((ShortCircuitableValidator) validator).isShortCircuit()) { - // get number of existing errors - List errs = null; - - if (fValidator != null) { - if (validatorContext.hasFieldErrors()) { - Collection fieldErrors = validatorContext.getFieldErrors().get(fullFieldName); - - if (fieldErrors != null) { - errs = new ArrayList<>(fieldErrors); - } - } - } else if (validatorContext.hasActionErrors()) { - Collection actionErrors = validatorContext.getActionErrors(); - - if (actionErrors != null) { - errs = new ArrayList(actionErrors); - } - } - - validator.validate(object); - - if (fValidator != null) { - if (validatorContext.hasFieldErrors()) { - Collection errCol = validatorContext.getFieldErrors().get(fullFieldName); - - if ((errCol != null) && !errCol.equals(errs)) { - LOG.debug("Short-circuiting on field validation"); - - if (shortcircuitedFields == null) { - shortcircuitedFields = new TreeSet<>(); - } - - shortcircuitedFields.add(fullFieldName); - } - } - } else if (validatorContext.hasActionErrors()) { - Collection errCol = validatorContext.getActionErrors(); - - if ((errCol != null) && !errCol.equals(errs)) { - LOG.debug("Short-circuiting"); - break; - } - } - continue; - } - - validator.validate(object); - } - finally { - validator.setValidatorContext(null); - } - } - } - - /** - * Builds a key for validators - used when caching validators. - * - * @param clazz the action. - * @param context the action's context. - * @return a validator key which is the class name plus context. - */ - protected static String buildValidatorKey(Class clazz, String context) { - StringBuilder sb = new StringBuilder(clazz.getName()); - sb.append("/"); - sb.append(context); - return sb.toString(); - } - - private List buildAliasValidatorConfigs(Class aClass, String context, boolean checkFile) { - String fileName = aClass.getName().replace('.', '/') + "-" + context + VALIDATION_CONFIG_SUFFIX; - - return loadFile(fileName, aClass, checkFile); - } - - private List buildClassValidatorConfigs(Class aClass, boolean checkFile) { - String fileName = aClass.getName().replace('.', '/') + VALIDATION_CONFIG_SUFFIX; - - return loadFile(fileName, aClass, checkFile); - } - - /** - *

    This method 'collects' all the validator configurations for a given - * action invocation.

    - * - *

    It will traverse up the class hierarchy looking for validators for every super class - * and directly implemented interface of the current action, as well as adding validators for - * any alias of this invocation. Nifty!

    - * - *

    Given the following class structure:

    - *
    -     *   interface Thing;
    -     *   interface Animal extends Thing;
    -     *   interface Quadraped extends Animal;
    -     *   class AnimalImpl implements Animal;
    -     *   class QuadrapedImpl extends AnimalImpl implements Quadraped;
    -     *   class Dog extends QuadrapedImpl;
    -     * 
    - * - *

    This method will look for the following config files for Dog:

    - *
    -     *   Animal
    -     *   Animal-context
    -     *   AnimalImpl
    -     *   AnimalImpl-context
    -     *   Quadraped
    -     *   Quadraped-context
    -     *   QuadrapedImpl
    -     *   QuadrapedImpl-context
    -     *   Dog
    -     *   Dog-context
    -     * 
    - * - *

    Note that the validation rules for Thing is never looked for because no class in the - * hierarchy directly implements Thing.

    - * - * @param clazz the Class to look up validators for. - * @param context the context to use when looking up validators. - * @param checkFile true if the validation config file should be checked to see if it has been - * updated. - * @param checked the set of previously checked class-contexts, null if none have been checked - * @return a list of validator configs for the given class and context. - */ - private List buildValidatorConfigs(Class clazz, String context, boolean checkFile, Set checked) { - List validatorConfigs = new ArrayList<>(); - - if (checked == null) { - checked = new TreeSet(); - } else if (checked.contains(clazz.getName())) { - return validatorConfigs; - } - - if (clazz.isInterface()) { - for (Class anInterface : clazz.getInterfaces()) { - validatorConfigs.addAll(buildValidatorConfigs(anInterface, context, checkFile, checked)); - } - } else { - if (!clazz.equals(Object.class)) { - validatorConfigs.addAll(buildValidatorConfigs(clazz.getSuperclass(), context, checkFile, checked)); - } - } - - // look for validators for implemented interfaces - for (Class anInterface1 : clazz.getInterfaces()) { - if (checked.contains(anInterface1.getName())) { - continue; - } - - validatorConfigs.addAll(buildClassValidatorConfigs(anInterface1, checkFile)); - - if (context != null) { - validatorConfigs.addAll(buildAliasValidatorConfigs(anInterface1, context, checkFile)); - } - - checked.add(anInterface1.getName()); - } - - validatorConfigs.addAll(buildClassValidatorConfigs(clazz, checkFile)); - - if (context != null) { - validatorConfigs.addAll(buildAliasValidatorConfigs(clazz, context, checkFile)); - } - - checked.add(clazz.getName()); - - return validatorConfigs; - } - - private List loadFile(String fileName, Class clazz, boolean checkFile) { - List retList = Collections.emptyList(); - URL fileUrl = ClassLoaderUtil.getResource(fileName, clazz); - if ((checkFile && fileManager.fileNeedsReloading(fileUrl)) || !validatorFileCache.containsKey(fileName)) { - try (InputStream is = fileManager.loadFile(fileUrl)) { - if (is != null) { - retList = new ArrayList<>(validatorFileParser.parseActionValidatorConfigs(validatorFactory, is, fileName)); - } - } catch (IOException e) { - LOG.error("Caught exception while loading file {}", fileName, e); - } - - validatorFileCache.put(fileName, retList); - } else { - retList = validatorFileCache.get(fileName); - } - - return retList; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/DefaultValidatorFactory.java b/core/src/main/java/com/opensymphony/xwork2/validator/DefaultValidatorFactory.java deleted file mode 100644 index d4d7ff74d9..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/DefaultValidatorFactory.java +++ /dev/null @@ -1,191 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.XWorkException; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ClassLoaderUtil; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.io.File; -import java.io.FilenameFilter; -import java.io.IOException; -import java.io.InputStream; -import java.net.URI; -import java.net.URL; -import java.util.*; -import java.util.zip.ZipEntry; -import java.util.zip.ZipInputStream; - - -/** - * Default validator factory - * - * @version $Date$ $Id$ - * @author Jason Carreira - * @author James House - */ -public class DefaultValidatorFactory implements ValidatorFactory { - - protected Map validators = new HashMap<>(); - private static Logger LOG = LogManager.getLogger(DefaultValidatorFactory.class); - protected ObjectFactory objectFactory; - protected ValidatorFileParser validatorFileParser; - - @Inject - public DefaultValidatorFactory(@Inject ObjectFactory objectFactory, @Inject ValidatorFileParser parser) { - this.objectFactory = objectFactory; - this.validatorFileParser = parser; - parseValidators(); - } - - public Validator getValidator(ValidatorConfig cfg) { - - String className = lookupRegisteredValidatorType(cfg.getType()); - - Validator validator; - - try { - // instantiate the validator, and set configured parameters - //todo - can this use the ThreadLocal? - validator = objectFactory.buildValidator(className, cfg.getParams(), ActionContext.getContext().getContextMap()); - } catch (Exception e) { - final String msg = "There was a problem creating a Validator of type " + className + " : caused by " + e.getMessage(); - throw new XWorkException(msg, e, cfg); - } - - // set other configured properties - validator.setMessageKey(cfg.getMessageKey()); - validator.setDefaultMessage(cfg.getDefaultMessage()); - validator.setMessageParameters(cfg.getMessageParams()); - if (validator instanceof ShortCircuitableValidator) { - ((ShortCircuitableValidator) validator).setShortCircuit(cfg.isShortCircuit()); - } - - return validator; - } - - public void registerValidator(String name, String className) { - LOG.debug("Registering validator of class {} with name {}", className, name); - validators.put(name, className); - } - - public String lookupRegisteredValidatorType(String name) { - // lookup the validator class mapped to the type name - String className = validators.get(name); - - if (className == null) { - throw new IllegalArgumentException("There is no validator class mapped to the name " + name); - } - - return className; - } - - private void parseValidators() { - LOG.debug("Loading validator definitions."); - - List files = new ArrayList<>(); - try { - // Get custom validator configurations via the classpath - Iterator urls = ClassLoaderUtil.getResources("", DefaultValidatorFactory.class, false); - while (urls.hasNext()) { - URL u = urls.next(); - try { - URI uri = new URI(u.toExternalForm().replaceAll(" ", "%20")); - if (!uri.isOpaque() && "file".equalsIgnoreCase(uri.getScheme())) { - File f = new File(uri); - FilenameFilter filter = new FilenameFilter() { - public boolean accept(File file, String fileName) { - return fileName.contains("-validators.xml"); - } - }; - // First check if this is a directory - // If yes, then just do a "list" to get all files in this directory - // and match the filenames with *-validators.xml. If the filename - // matches then add to the list of files to be parsed - if (f.isDirectory()) { - try { - File[] ff = f.listFiles(filter); - if ( ff != null && ff.length > 0) { - files.addAll(Arrays.asList(ff)); - } - } catch (SecurityException se) { - LOG.error("Security Exception while accessing directory '{}'", f, se); - } - - } else { - // If this is not a directory, then get hold of the inputstream. - // If its not a ZipInputStream, then create a ZipInputStream out - // of it. The intention is to allow nested jar files to be scanned - // for *-validators.xml. - // Ex: struts-app.jar -> MyApp.jar -> Login-validators.xml should be - // parsed and loaded. - ZipInputStream zipInputStream = null; - try (InputStream inputStream = u.openStream()) { - if (inputStream instanceof ZipInputStream) { - zipInputStream = (ZipInputStream) inputStream; - } else { - zipInputStream = new ZipInputStream(inputStream); - } - ZipEntry zipEntry = zipInputStream.getNextEntry(); - while (zipEntry != null) { - if (zipEntry.getName().endsWith("-validators.xml")) { - LOG.trace("Adding validator {}", zipEntry.getName()); - files.add(new File(zipEntry.getName())); - } - zipEntry = zipInputStream.getNextEntry(); - } - } finally { - //cleanup - if (zipInputStream != null) { - zipInputStream.close(); - } - } - } - } - } catch (Exception ex) { - LOG.error("Unable to load {}", u, ex); - } - } - } catch (IOException e) { - throw new ConfigurationException("Unable to parse validators", e); - } - - // Parse default validator configurations - String resourceName = "com/opensymphony/xwork2/validator/validators/default.xml"; - retrieveValidatorConfiguration(resourceName); - - // Overwrite and extend defaults with application specific validator configurations - resourceName = "validators.xml"; - retrieveValidatorConfiguration(resourceName); - - // Add custom (plugin) specific validator configurations - for (File file : files) { - retrieveValidatorConfiguration(file.getName()); - } - } - - private void retrieveValidatorConfiguration(String resourceName) { - InputStream is = ClassLoaderUtil.getResourceAsStream(resourceName, DefaultValidatorFactory.class); - if (is != null) { - validatorFileParser.parseValidatorDefinitions(validators, is, resourceName); - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/FieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/FieldValidator.java deleted file mode 100644 index 3077671453..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/FieldValidator.java +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator; - -/** - * The FieldValidator interface defines the methods to be implemented by FieldValidators. - * Which are used by the XWork validation framework to validate Action properties before - * executing the Action. - */ -public interface FieldValidator extends Validator { - - /** - * Sets the field name to validate with this FieldValidator - * - * @param fieldName the field name - */ - void setFieldName(String fieldName); - - /** - * Gets the field name to be validated - * - * @return the field name - */ - String getFieldName(); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/ShortCircuitableValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/ShortCircuitableValidator.java deleted file mode 100644 index dde5044301..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/ShortCircuitableValidator.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator; - - -/** - * This interface should be implemented by validators that can short-circuit the validator queue - * that it is in. - * - * @author Mark Woon - */ -public interface ShortCircuitableValidator { - - /** - * Sets whether this field validator should short circuit the validator queue - * it's in if validation fails. - * - * @param shortcircuit true if this field validator should short circuit on - * failure, false otherwise - */ - void setShortCircuit(boolean shortcircuit); - - /** - * Gets whether this field validator should short circuit the validator queue - * it's in if validation fails. - * - * @return true if this field validator should short circuit on failure, - * false otherwise - */ - boolean isShortCircuit(); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/ValidationException.java b/core/src/main/java/com/opensymphony/xwork2/validator/ValidationException.java deleted file mode 100644 index 2573b9f58d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/ValidationException.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator; - - -/** - * ValidationException. - * - * @author Jason Carreira - */ -public class ValidationException extends Exception { - - /** - * Constructs an Exception with no specified detail message. - */ - public ValidationException() { - } - - /** - * Constructs an Exception with the specified detail message. - * - * @param s the detail message. - */ - public ValidationException(String s) { - super(s); - } - - public ValidationException(String message, Throwable cause) { - super(message, cause); - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/Validator.java b/core/src/main/java/com/opensymphony/xwork2/validator/Validator.java deleted file mode 100644 index 43dda0fcd1..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/Validator.java +++ /dev/null @@ -1,486 +0,0 @@ -/* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator; - -import com.opensymphony.xwork2.util.ValueStack; - - -/** - * - *

    The validators supplied by the XWork distribution (and any validators you - * might write yourself) come in two different flavors:

    - * - *
      - *
    1. Plain Validators / Non-Field validators
    2. - *
    3. FieldValidators
    4. - *
    - * - *

    Plain Validators (such as the ExpressionValidator) perform validation checks - * that are not inherently tied to a single specified field. When you declare a - * plain Validator in your -validation.xml file you do not associate a fieldname - * attribute with it. (You should avoid using plain Validators within the - * <field-validator> syntax described below.)

    - * - *

    FieldValidators (such as the EmailValidator) are designed to perform - * validation checks on a single field. They require that you specify a fieldname - * attribute in your -validation.xml file. There are two different (but equivalent) - * XML syntaxes you can use to declare FieldValidators (see "<validator> vs. - * <field-Validator> syntax" below).

    - * - *

    There are two places where the differences between the two validator flavors - * are important to keep in mind:

    - * - *
      - *
    1. when choosing the xml syntax used for declaring a validator - * (either <validator> or <field-validator>)
    2. - *
    3. when using the short-circuit capability
    4. - *
    - * - *

    NOTE:Note that you do not declare what "flavor" of validator you are - * using in your -validation.xml file, you just declare the name of the validator - * to use and Struts will know whether it's a "plain Validator" or a "FieldValidator" - * by looking at the validation class that the validator's programmer chose - * to implement.

    - * - * - * - * - *

    To define validation rules for an Action, create a file named ActionName-validation.xml - * in the same package as the Action. You may also create alias-specific validation rules which - * add to the default validation rules defined in ActionName-validation.xml by creating - * another file in the same directory named ActionName-aliasName-validation.xml. In both - * cases, ActionName is the name of the Action class, and aliasName is the name of the - * Action alias defined in the xwork.xml configuration for the Action.

    - * - *

    The framework will also search up the inheritance tree of the Action to - * find validation rules for directly implemented interfaces and parent classes of the Action. - * This is particularly powerful when combined with ModelDriven Actions and the VisitorFieldValidator. - * Here's an example of how validation rules are discovered. Given the following class structure:

    - * - *
      - *
    • interface Animal;
    • - *
    • interface Quadraped extends Animal;
    • - *
    • class AnimalImpl implements Animal;
    • - *
    • class QuadrapedImpl extends AnimalImpl implements Quadraped;
    • - *
    • class Dog extends QuadrapedImpl;
    • - *
    - * - *

    The framework method will look for the following config files if Dog is to be validated:

    - * - *
      - *
    • Animal
    • - *
    • Animal-aliasname
    • - *
    • AnimalImpl
    • - *
    • AnimalImpl-aliasname
    • - *
    • Quadraped
    • - *
    • Quadraped-aliasname
    • - *
    • QuadrapedImpl
    • - *
    • QuadrapedImpl-aliasname
    • - *
    • Dog
    • - *
    • Dog-aliasname
    • - *
    - * - *

    While this process is similar to what the XW:Localization framework does - * when finding messages, there are some subtle differences. The most important - * difference is that validation rules are discovered from the parent downwards. - *

    - * - *

    NOTE:Child's *-validation.xml will add on to parent's *-validation.xml - * according to the class hierarchy defined above. With this feature, one could have - * more generic validation rule at the parent and more specific validation rule at - * the child.

    - * - * - * - * - * - *

    There are two ways you can define validators in your -validation.xml file:

    - *
      - *
    1. <validator>
    2. - *
    3. <field-validator>
    4. - *
    - *

    Keep the following in mind when using either syntax:

    - * - *

    Non-Field-Validator - * The <validator> element allows you to declare both types of validators - * (either a plain Validator a field-specific FieldValidator).

    - * - * - *
    - * 
    - *    <!-- Declaring a plain Validator using the <validator> syntax: -->
    - *
    - *    <validator type="expression>
    - *          <param name="expression">foo gt bar</param>
    - *          <message>foo must be great than bar.</message>
    - *    </validator>
    - * 
    - * 
    - * - *
    - * 
    - *    <!-- Declaring a field validator using the <validator> syntax; -->
    - *
    - *    <validator type="required">
    - *         <param name="fieldName">bar</param>
    - *         <message>You must enter a value for bar.</message>
    - *    </validator>
    - * 
    - * 
    - * - * - *

    field-validator - * The <field-validator> elements are basically the same as the <validator> elements - * except that they inherit the fieldName attribute from the enclosing <field> element. - * FieldValidators defined within a <field-validator> element will have their fieldName - * automatically filled with the value of the parent <field> element's fieldName - * attribute. The reason for this structure is to conveniently group the validators - * for a particular field under one element, otherwise the fieldName attribute - * would have to be repeated, over and over, for each individual <validator>.

    - * - *

    HINT: - * It is always better to defined field-validator inside a <field> tag instead of - * using a <validator> tag and supplying fieldName as its param as the xml code itself - * is clearer (grouping of field is clearer)

    - * - *

    NOTE: - * Note that you should only use FieldValidators (not plain Validators) within a - * <field-validator> block. A plain Validator inside a <field> will not be - * allowed and would generate error when parsing the xml, as it is not allowed in - * the defined dtd (xwork-validator-1.0.2.dtd)

    - * - * - *
    - * 
    - * Declaring a FieldValidator using the <field-validator> syntax:
    - *
    - * <field name="email_address">
    - *   <field-validator type="required">
    - *       <message>You cannot leave the email address field empty.</message>
    - *   </field-validator>
    - *   <field-validator type="email">
    - *       <message>The email address you entered is not valid.</message>
    - *   </field-validator>
    - * </field>
    - * 
    - * 
    - * - * - * - *

    The choice is yours. It's perfectly legal to only use <validator> elements - * without the <field> elements and set the fieldName attribute for each of them. - * The following are effectively equal:

    - * - * - *
    - * 
    - * <field name="email_address">
    - *   <field-validator type="required">
    - *       <message>You cannot leave the email address field empty.</message>
    - *   </field-validator>
    - *   <field-validator type="email">
    - *       <message>The email address you entered is not valid.</message>
    - *   </field-validator>
    - * </field>
    - *
    - *
    - * <validator type="required">
    - *   <param name="fieldName">email_address</param>
    - *   <message>You cannot leave the email address field empty.</message>
    - * </validator>
    - * <validator type="email">
    - *   <param name="fieldName">email_address</param>
    - *   <message>The email address you entered is not valid.</message>
    - * </validator>
    - * 
    - * 
    - * - * - * - *

    It is possible to short-circuit a stack of validators. - * Here is another sample config file containing validation rules from the - * Xwork test cases: Notice that some of the <field-validator> and - * <validator> elements have the short-circuit attribute set to true.

    - * - * - *
    - * <!-- START SNIPPET: exShortCircuitingValidators -->
    - * <!DOCTYPE validators PUBLIC
    - *         "-//Apache Struts//XWork Validator 1.0.3//EN"
    - *  	   "http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
    - * <validators>
    - *   <!-- Field Validators for email field -->
    - *   <field name="email">
    - *       <field-validator type="required" short-circuit="true">
    - *           <message>You must enter a value for email.</message>
    - *       </field-validator>
    - *       <field-validator type="email" short-circuit="true">
    - *           <message>Not a valid e-mail.</message>
    - *       </field-validator>
    - *   </field>
    - *   <!-- Field Validators for email2 field -->
    - *   <field name="email2">
    - *      <field-validator type="required">
    - *           <message>You must enter a value for email2.</message>
    - *       </field-validator>
    - *      <field-validator type="email">
    - *           <message>Not a valid e-mail2.</message>
    - *       </field-validator>
    - *   </field>
    - *   <!-- Plain Validator 1 -->
    - *   <validator type="expression">
    - *       <param name="expression">email.equals(email2)</param>
    - *       <message>Email not the same as email2</message>
    - *   </validator>
    - *   <!-- Plain Validator 2 -->
    - *   <validator type="expression" short-circuit="true">
    - *       <param name="expression">email.startsWith('mark')</param>
    - *       <message>Email does not start with mark</message>
    - *   </validator>
    - * </validators>
    - * <!-- END SNIPPET: exShortCircuitingValidators -->
    - * 
    - * - * - *

    short-circuiting and Validator flavors

    - *

    Plain validator takes precedence over field-validator. They get validated - * first in the order they are defined and then the field-validator in the order - * they are defined. Failure of a particular validator marked as short-circuit - * will prevent the evaluation of subsequent validators and an error (action - * error or field error depending on the type of validator) will be added to - * the ValidationContext of the object being validated.

    - * - *

    In the example above, the actual execution of validator would be as follows:

    - * - *
      - *
    1. Plain Validator 1
    2. - *
    3. Plain Validator 2
    4. - *
    5. Field Validators for email field
    6. - *
    7. Field Validators for email2 field
    8. - *
    - * - *

    Since Plain Validator 2 is short-circuited, if its validation failed, - * it will causes Field validators for email field and Field validators for email2 - * field to not be validated as well.

    - * - *

    Usefull Information: - * More complicated validation should probably be done in the validate() - * method on the action itself (assuming the action implements Validatable - * interface which ActionSupport already does).

    - * - *

    - * A plain Validator (non FieldValidator) that gets short-circuited will - * completely break out of the validation stack. No other validators will be - * evaluated and plain validators takes precedence over field validators meaning - * that they get evaluated in the order they are defined before field validators - * get a chance to be evaluated. - *

    - * - * - * - *

    Short cuircuiting and validator flavours

    - *

    A FieldValidator that gets short-circuited will only prevent other - * FieldValidators for the same field from being evaluated. Note that this - * "same field" behavior applies regardless of whether the <validator> or - * <field-validator> syntax was used to declare the validation rule. - * By way of example, given this -validation.xml file:

    - * - * - *
    - * 
    - * <validator type="required" short-circuit="true">
    - *   <param name="fieldName">bar</param>
    - *   <message>You must enter a value for bar.</message>
    - * </validator>
    - *
    - * <validator type="expression">
    - *   <param name="expression">foo gt bar</param>
    - *   <message>foo must be great than bar.</message>
    - * </validator>
    - * 
    - * 
    - * - * - *

    both validators will be run, even if the "required" validator short-circuits. - * "required" validators are FieldValidator's and will not short-circuit the plain - * ExpressionValidator because FieldValidators only short-circuit other checks on - * that same field. Since the plain Validator is not field specific, it is - * not short-circuited.

    - * - * - * - * - *

    As mentioned above, the framework will also search up the inheritance tree - * of the action to find default validations for interfaces and parent classes of - * the Action. If you are using the short-circuit attribute and relying on - * default validators higher up in the inheritance tree, make sure you don't - * accidentally short-circuit things higher in the tree that you really want!

    - *

    - * The effect of having common validators on both - *

    - *
      - *
    • <actionClass>-validation.xml
    • - *
    • <actionClass>-<actionAlias>-validation.xml
    • - *
    - *

    - * It should be noted that the nett effect will be validation on both the validators available - * in both validation configuration file. For example if we have 'requiredstring' validators defined - * in both validation xml file for field named 'address', we will see 2 validation error indicating that - * the the address cannot be empty (assuming validation failed). This is due to WebWork - * will merge validators found in both validation configuration files. - *

    - *

    - * The logic behind this design decision is such that we could have common validators in - * <actionClass>-validation.xml and more context specific validators to be located - * in <actionClass>-<actionAlias>-validation.xml - *

    - * - * - * - * - * Validator's validation messages could be internatinalized. For example, - *
    - *   <field-validator type="required">
    - *      <message key="required.field" />
    - *   </field-validator>
    - * 
    - * or - *
    - *   <validator type="expression">
    - *      <param name="expression">email.startsWith('Mark')</param>
    - *      <message key="email.invalid" />
    - *   </validator>
    - * 
    - * In the first case, WebWork would look for i18n with key 'required.field' as the validation error message if - * validation fails, and 'email.invalid' in the second case. - * - * We could also provide a default message such that if validation failed and the i18n key for the message - * cannot be found, WebWork would fall back and use the default message. An example would be as follows :- - *
    - *   <field-validator type="required">
    - *      <message key="required.field">This field is required.</message>
    - *   </field-validator>
    - * 
    - * or - *
    - *   <validator type="expression">
    - *      <param name="expression">email.startsWith('Mark')</param>
    - *      <message key="email.invalid">Email needs with starts with Mark</message>
    - *   </validator>
    - * 
    - * - * - * - * @author Jason Carreira - */ -public interface Validator { - - /** - * Sets the default message to use for validation failure - * - * @param message the default message - */ - void setDefaultMessage(String message); - - /** - * Gets the default message used for validation failures - * - * @return the default message - */ - String getDefaultMessage(); - - /** - * Gets the validation failure message for the given object - * - * @param object object being validated (eg. a domain model object) - * @return the validation failure message - */ - String getMessage(Object object); - - /** - * Sets a resource bundle key to be used for lookup of validation failure message - * - * @param key the resource bundle key - */ - void setMessageKey(String key); - - /** - * Gets the resource bundle key used for lookup of validation failure message - * - * @return the resource bundle key - */ - String getMessageKey(); - - /** - * Sets the message parameters to be used when parsing i18n messages - * - * @param messageParameters the message parameters - */ - void setMessageParameters(String[] messageParameters); - - /** - * Gets the message parameters to be used when parsing i18n messages - * - * @return the message parameters - */ - String[] getMessageParameters(); - - /** - * This method will be called before validate with a non-null ValidatorContext. - * - * @param validatorContext the validation context to use. - */ - void setValidatorContext(ValidatorContext validatorContext); - - /** - * Gets the validation context used - * - * @return the validation context - */ - ValidatorContext getValidatorContext(); - - /** - * The validation implementation must guarantee that setValidatorContext will - * be called with a non-null ValidatorContext before validate is called. - * - * @param object the object to be validated. - * @throws ValidationException is thrown if there is validation error(s). - */ - void validate(Object object) throws ValidationException; - - /** - * Sets the validator type to use (see class javadoc). - * - * @param type the type to use. - */ - void setValidatorType(String type); - - /** - * Gets the validator type used (see class javadoc). - * - * @return the type used - */ - String getValidatorType(); - - /** - * Sets the value stack to use to resolve values and parameters - * - * @param stack The value stack for the request - * @since 2.1.1 - */ - void setValueStack(ValueStack stack); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorContext.java b/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorContext.java deleted file mode 100644 index 82d01fd796..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorContext.java +++ /dev/null @@ -1,38 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator; - -import com.opensymphony.xwork2.LocaleProvider; -import com.opensymphony.xwork2.TextProvider; -import com.opensymphony.xwork2.interceptor.ValidationAware; - - -/** - * The context for validation. This interface extends others to provide methods for reporting - * errors and messages as well as looking up error messages in a resource bundle using a specific locale. - * - * @author Jason Carreira - */ -public interface ValidatorContext extends ValidationAware, TextProvider, LocaleProvider { - - /** - * Translates a simple field name into a full field name in OGNL syntax. - * - * @param fieldName the field name to lookup. - * @return the full field name in OGNL syntax. - */ - String getFullFieldName(String fieldName); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java b/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java deleted file mode 100644 index f3bb27a414..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFactory.java +++ /dev/null @@ -1,237 +0,0 @@ -package com.opensymphony.xwork2.validator; - -/** - * ValidatorFactory - * - *

    - * - * Validation rules are handled by validators, which must be registered with - * the ValidatorFactory (using the registerValidator method). The simplest way to do so is to add a file name - * validators.xml in the root of the classpath (/WEB-INF/classes) that declares - * all the validators you intend to use. - * - *

    - * - * - *

    - * INFORMATION - * - * validators.xml if being defined should be available in the classpath. However - * this is not necessary, if no custom validator is needed. Predefined sets of validators - * will automatically be picked up when defined in - * com/opensymphony/xwork2/validator/validators/default.xml packaged in - * in the xwork jar file. See ValidatorFactory static block for details. - * - *

    - * - *

    - * WARNING - * - * If custom validator is being defined and a validators.xml is created and - * place in the classpath, do remember to copy all the other pre-defined validators - * that is needed into the validators.xml as if not they will not be registered. - * Once a validators.xml is detected in the classpath, the default one - * (com/opensymphony/xwork2/validator/validators/default.xml) will not be loaded. - * It is only loaded when a custom validators.xml cannot be found in the classpath. - * Be careful. - * - *

    - * - *

    Note: - * - * The default validationWorkflowStack already includes this.
    - * All that is required to enable validation for an Action is to put the - * ValidationInterceptor in the interceptor refs of the action (see xwork.xml) like so: - * - *

    - * - *
    - * 
    - *     <interceptor name="validator" class="com.opensymphony.xwork2.validator.ValidationInterceptor"/>
    - * 
    - * 
    - * - *

    Field Validators - * - * Field validators, as the name indicate, act on single fields accessible through an action. - * A validator, in contrast, is more generic and can do validations in the full action context, - * involving more than one field (or even no field at all) in validation rule. - * Most validations can be defined on per field basis. This should be preferred over - * non-field validation wherever possible, as field validator messages are bound to the - * related field and will be presented next to the corresponding input element in the - * respecting view. - * - *

    - * - *

    Non Field Validators - * - * Non-field validators only add action level messages. Non-field validators - * are mostly domain specific and therefore offer custom implementations. - * The most important standard non-field validator provided by XWork - * is ExpressionValidator. - * - *

    - * - *

    NOTE: - * - * Non-field validators takes precedence over field validators - * regardless of the order they are defined in *-validation.xml. If a non-field - * validator is short-circuited, it will causes its non-field validator to not - * being executed. See validation framework documentation for more info. - * - *

    - * - *

    VALIDATION RULES:

    - * - *

    Validation rules can be specified:

    - *
      - *
    1. Per Action class: in a file named ActionName-validation.xml
    2. - *
    3. Per Action alias: in a file named ActionName-alias-validation.xml
    4. - *
    5. Inheritance hierarchy and interfaces implemented by Action class: - * XWork searches up the inheritance tree of the action to find default - * validations for parent classes of the Action and interfaces implemented
    6. - *
    - *

    Here is an example for SimpleAction-validation.xml:

    - * - * - *
    - * 
    - * <!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.3//EN"
    -   		"http://struts.apache.org/dtds/xwork-validator-1.0.3.dtd">
    - * <validators>
    - *   <field name="bar">
    - *       <field-validator type="required">
    - *           <message>You must enter a value for bar.</message>
    - *       </field-validator>
    - *       <field-validator type="int">
    - *           <param name="min">6</param>
    - *           <param name="max">10</param>
    - *           <message>bar must be between ${min} and ${max}, current value is ${bar}.</message>
    - *       </field-validator>
    - *   </field>
    - *   <field name="bar2">
    - *       <field-validator type="regex">
    - *           <param name="expression">[0-9],[0-9]</param>
    - *           <message>The value of bar2 must be in the format "x, y", where x and y are between 0 and 9</message>
    - *      </field-validator>
    - *   </field>
    - *   <field name="date">
    - *       <field-validator type="date">
    - *           <param name="min">12/22/2002</param>
    - *           <param name="max">12/25/2002</param>
    - *           <message>The date must be between 12-22-2002 and 12-25-2002.</message>
    - *       </field-validator>
    - *   </field>
    - *   <field name="foo">
    - *       <field-validator type="int">
    - *           <param name="min">0</param>
    - *           <param name="max">100</param>
    - *           <message key="foo.range">Could not find foo.range!</message>
    - *       </field-validator>
    - *   </field>
    - *   <validator type="expression">
    - *       <param name="expression">foo lt bar </param>
    - *       <message>Foo must be greater than Bar. Foo = ${foo}, Bar = ${bar}.</message>
    - *   </validator>
    - * </validators>
    - * 
    - * 
    - * - * - *

    - * - * Here we can see the configuration of validators for the SimpleAction class. - * Validators (and field-validators) must have a type attribute, which refers - * to a name of an Validator registered with the ValidatorFactory as above. - * Validator elements may also have <param> elements with name and value attributes - * to set arbitrary parameters into the Validator instance. See below for discussion - * of the message element. - * - *

    - * - * - * - * - *

    Each Validator or Field-Validator element must define one message element inside - * the validator element body. The message element has 1 attributes, key which is not - * required. The body of the message tag is taken as the default message which should - * be added to the Action if the validator fails. Key gives a message key to look up - * in the Action's ResourceBundles using getText() from LocaleAware if the Action - * implements that interface (as ActionSupport does). This provides for Localized - * messages based on the Locale of the user making the request (or whatever Locale - * you've set into the LocaleAware Action). After either retrieving the message from - * the ResourceBundle using the Key value, or using the Default message, the current - * Validator is pushed onto the ValueStack, then the message is parsed for \$\{...\} - * sections which are replaced with the evaluated value of the string between the - * \$\{ and \}. This allows you to parameterize your messages with values from the - * Validator, the Action, or both.

    - * - * - *

    If the validator fails, the validator is pushed onto the ValueStack and the - * message - either the default or the locale-specific one if the key attribute is - * defined (and such a message exists) - is parsed for ${...} sections which are - * replaced with the evaluated value of the string between the ${ and }. This - * allows you to parameterize your messages with values from the validator, the - * Action, or both.

    - * - *

    NOTE: Since validation rules are in an XML file, you must make sure - * you escape special characters. For example, notice that in the expression - * validator rule above we use "&gt;" instead of ">". Consult a resource on XML - * for the full list of characters that must be escaped. The most commonly used - * characters that must be escaped are: & (use &amp;), > (user &gt;), and < (use &lt;).

    - * - *

    Here is an example of a parameterized message:

    - *

    This will pull the min and max parameters from the IntRangeFieldValidator and - * the value of bar from the Action.

    - * - * - *
    - * 
    - *    bar must be between ${min} and ${max}, current value is ${bar}.
    - * 
    - * 
    - * - * - *

    Another notable fact is that the provided message value is capable of containing OGNL expressions. - * Keeping this in mind, it is possible to construct quite sophisticated messages.

    - *

    See the following example to get an impression:

    - * - * - * - *
    - * 
    - *    <message>${getText("validation.failednotice")}! ${getText("reason")}: ${getText("validation.inputrequired")}</message>
    - * 
    - * 
    - * - * @author Jason Carreira - * @author James House - */ -public interface ValidatorFactory { - - /** - * Get a Validator that matches the given configuration. - * - * @param cfg the configurator. - * @return the validator. - */ - Validator getValidator(ValidatorConfig cfg); - - /** - * Registers the given validator to the existing map of validators. - * This will add to the existing list. - * - * @param name name of validator to add. - * @param className the FQ classname of the validator. - */ - void registerValidator(String name, String className); - - /** - * Lookup to get the FQ classname of the given validator name. - * - * @param name name of validator to lookup. - * @return the found FQ classname - * @throws IllegalArgumentException is thrown if the name is not found. - */ - String lookupRegisteredValidatorType(String name); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFileParser.java b/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFileParser.java deleted file mode 100644 index 25b8b11e49..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/ValidatorFileParser.java +++ /dev/null @@ -1,48 +0,0 @@ -package com.opensymphony.xwork2.validator; - -import java.io.InputStream; -import java.util.List; -import java.util.Map; - -/** - * This class serves 2 purpose : - *
      - *
    • - * Parse the validation config file. (eg. MyAction-validation.xml, MyAction-actionAlias-validation.xml) - * to return a List of ValidatorConfig encapsulating the validator information. - *
    • - *
    • - * Parse the validator definition file, (eg. validators.xml) that defines the {@link Validator}s - * registered with XWork. - *
    • - *
    - * - * @author Jason Carreira - * @author James House - * @author tm_jee ( tm_jee (at) yahoo.co.uk ) - * @author Rob Harrop - * @author Rene Gielen - * - * @see com.opensymphony.xwork2.validator.ValidatorConfig - */ -public interface ValidatorFileParser { - /** - * Parse resource for a list of ValidatorConfig objects (configuring which validator(s) are - * being applied to a particular field etc.) - * - * @param validatorFactory a validator factory - * @param is input stream to the resource - * @param resourceName file name of the resource - * @return List list of ValidatorConfig - */ - List parseActionValidatorConfigs(ValidatorFactory validatorFactory, InputStream is, String resourceName); - - /** - * Parses validator definitions (register various validators with XWork). - * - * @param validators map of validators - * @param is The input stream - * @param resourceName The location of the input stream - */ - void parseValidatorDefinitions(Map validators, InputStream is, String resourceName); -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ConditionalVisitorFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ConditionalVisitorFieldValidator.java deleted file mode 100644 index 3830774f0f..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ConditionalVisitorFieldValidator.java +++ /dev/null @@ -1,166 +0,0 @@ -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - *

    - * The validator allows you to forward validator to object properties of your action - * using the objects own validator files. This allows you to use the ModelDriven development - * pattern and manage your validations for your models in one place, where they belong, next to - * your model classes. - *

    - * - *

    - * The ConditionalVisitorFieldValidator can handle either simple Object properties, Collections of Objects, or Arrays. - * The error message for the ConditionalVisitorFieldValidator will be appended in front of validator messages added - * by the validations for the Object message. - *

    - * - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    expressionyes Boolean conditional expression
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    context no action alias Determines the context to use for validating the Object property. If not defined, the context of the Action validation is propagated to the Object property validation. In the case of Action validation, this context is the Action alias.
    appendPrefix no true Determines whether the field name of this field validator should be prepended to the field name of the visited field to determine the full field name when an error occurs. For example, suppose that the bean being validated has a "name" property. If appendPrefix is true, then the field error will be stored under the field "bean.name". If appendPrefix is false, then the field error will be stored under the field "name".
    If you are using the VisitorFieldValidator to validate the model from a ModelDriven Action, you should set appendPrefix to false unless you are using "model.name" to reference the properties on your model.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @ConditionalVisitorFieldValidator(expression="app.appid > 100",  message = "Default message", key = "i18n.key", shortCircuit = true, context = "action alias", appendPrefix = true)
    - * 
    - * 
    - * - * @author Matt Raible - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface ConditionalVisitorFieldValidator { - - /** - * Determines the context to use for validating the Object property. - * If not defined, the context of the Action validator is propagated to the Object property validator. - * In the case of Action validator, this context is the Action alias. - * - * @return the context - */ - String context() default ""; - - /** - * Determines whether the field name of this field validator should be prepended to the field name of - * the visited field to determine the full field name when an error occurs. For example, suppose that - * the bean being validated has a 'name' property. - * - * If appendPrefix is true, then the field error will be stored under the field 'bean.name'. - * If appendPrefix is false, then the field error will be stored under the field 'name'. - * - * If you are using the ConditionalVisitorFieldValidator to validate the model from a ModelDriven Action, - * you should set appendPrefix to false unless you are using "model.name" to reference the properties - * on your model. - * - * @return if append prefix - */ - boolean appendPrefix() default true; - - /** - * @return The conditional expression. - */ - String expression(); - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit='true' attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ConversionErrorFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ConversionErrorFieldValidator.java deleted file mode 100644 index b1f4585975..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ConversionErrorFieldValidator.java +++ /dev/null @@ -1,139 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This validator checks if there are any conversion errors for a field and applies them if they exist. - * See Type Conversion Error Handling for details. - * - * - *

    Annotation usage:

    - * - * - *

    The ConversionErrorFieldValidator annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @ConversionErrorFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface ConversionErrorFieldValidator { - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit="true" attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return Defines to repopulate field or not after validation, default false - */ - boolean repopulateField() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType type() default ValidatorType.FIELD; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/DateRangeFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/DateRangeFieldValidator.java deleted file mode 100644 index 30c4d84379..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/DateRangeFieldValidator.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This validator checks that a date field has a value within a specified range. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
    min no   Date property. The minimum the date must be.
    minExpressionno OGNL expression used to obtain the minimum the date must be.
    max no   Date property. The maximum date can be.
    maxExpressionno OGNL expression used to obtain the maximum date can be.
    maxExpressionno OGNL expression used to obtain the maximum date can be.
    dateFormatno Format used to parse min/max value.
    - * - *

    If neither min nor max is set, nothing will be done.

    - * - * - *

    Example code:

    - * - *
    - * 
    - * @DateRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "2005/01/01", max = "2005/12/31")
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface DateRangeFieldValidator { - - /** - * Date property. - * - * @return The minimum the date must be. - */ - String min() default ""; - - /** - * @return An expression which will be evaluated against the Value Stack to get the min value - */ - String minExpression() default ""; - - /** - * Date property. - * - * @return The maximum date can be. - */ - String max() default ""; - - /** - * @return An expression which will be evaluated against the Value Stack to get the max value - */ - String maxExpression() default ""; - - /** - * @return Date format used to parse min and max value - */ - String dateFormat() default ""; - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit="true" attribute value if true. - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType type() default ValidatorType.FIELD; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/DoubleRangeFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/DoubleRangeFieldValidator.java deleted file mode 100644 index 614931c916..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/DoubleRangeFieldValidator.java +++ /dev/null @@ -1,233 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This validator checks that a double field has a value within a specified range. - * If neither min nor max is set, nothing will be done. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
    minInclusive no   Double property. The inclusive minimum the number must be.
    minInclusiveExpressionno OGNL expression used to obtain the inclusive minimum the number must be.
    maxInclusive no   Double property. The inclusive maximum number can be.
    maxInclusiveExpression no  OGNL expression used to obtain the inclusive maximum number can be.
    minExclusive no   Double property. The exclusive minimum the number must be.
    minExclusiveExpression no  OGNL expression used to obtain the exclusive minimum the number must be.
    maxExclusive no   Double property. The exclusive maximum number can be.
    maxExclusiveExpression no  OGNL expression used to obtain the exclusive maximum number can be.
    - * - *

    If neither min nor max is set, nothing will be done.

    - * - *

    The values for min and max must be inserted as String values so that "0" can be handled as a possible value.

    - * - * - *

    Example code:

    - * - *
    - * 
    - * @DoubleRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, minInclusive = "0.123", maxInclusive = "99.987")
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface DoubleRangeFieldValidator { - - /** - * Double property. - * - * @return The inclusive minimum the number must be. - */ - String minInclusive() default ""; - - /** - * @return The inclusive minimum the number must be defined as an expression - */ - String minInclusiveExpression() default ""; - - /** - * Double property. - * - * @return The inclusive minimum the number must be. - */ - String maxInclusive() default ""; - - /** - * @return The inclusive minimum the number must be defined as an expression - */ - String maxInclusiveExpression() default ""; - - /** - * Double property. - * - * @return The exclusive maximum number can be. - */ - String minExclusive() default ""; - - /** - * @return The exclusive maximum number can be defined as an expression - */ - String minExclusiveExpression() default ""; - - /** - * Double property. - * - * @return The exclusive maximum number can be. - */ - String maxExclusive() default ""; - - /** - * @return The exclusive maximum number can be defined as an expression - */ - String maxExclusiveExpression() default ""; - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit="true" attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType type() default ValidatorType.FIELD; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/EmailValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/EmailValidator.java deleted file mode 100644 index a96ad6d4b3..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/EmailValidator.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This validator checks that a field is a valid e-mail address if it contains a non-empty String. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @EmailValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface EmailValidator { - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit='true' attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType type() default ValidatorType.FIELD; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ExpressionValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ExpressionValidator.java deleted file mode 100644 index d5db36090b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ExpressionValidator.java +++ /dev/null @@ -1,123 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This non-field level validator validates a supplied regular expression. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    expression yes   An OGNL expression that returns a boolean value.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @ExpressionValidator(message = "Default message", key = "i18n.key", shortCircuit = true, expression = "an OGNL expression" )
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Retention(RetentionPolicy.RUNTIME) -@Target({ ElementType.METHOD}) -public @interface ExpressionValidator { - - /** - * @return The expressions to validate. - * An OGNL expression that returns a boolean value. - */ - String expression(); - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit="true" attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/FieldExpressionValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/FieldExpressionValidator.java deleted file mode 100644 index 559c53d8b4..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/FieldExpressionValidator.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This validator uses an OGNL expression to perform its validator. - * The error message will be added to the field if the expression returns - * false when it is evaluated against the value stack. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    expression yes   An OGNL expression that returns a boolean value.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @FieldExpressionValidator(message = "Default message", key = "i18n.key", shortCircuit = true, expression = "an OGNL expression")
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface FieldExpressionValidator { - - /** - * @return An OGNL expression that returns a boolean value. - */ - String expression(); - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit='true' attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/IntRangeFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/IntRangeFieldValidator.java deleted file mode 100644 index b3ccaffb42..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/IntRangeFieldValidator.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This validator checks that a numeric field has a value within a specified range. - * If neither min nor max is set, nothing will be done. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
    min no   Integer property. The minimum the number must be.
    minExpression no  OGNL expression used to obtain the minimum the number must be.
    max no   Integer property. The maximum number can be. Can be an expression.!
    maxExpression no  OGNL expression used to obtain the maximum number can be.
    parsenofalseEnable parsing of min/max value.
    - * - *

    If neither min nor max is set, nothing will be done.

    - * - *

    The values for min and max must be inserted as String values so that "0" can be handled as a possible value.

    - * - * - *

    Example code:

    - * - *
    - * 
    - * @IntRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "0", max = "42")
    - *
    - * @IntRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, minExpression = "${minValue}", maxExpression = "${maxValue}")
    - * 
    - * 
    - * - * - * @author Rainer Hermanns - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface IntRangeFieldValidator { - - /** - * Integer property. - * - * @return The minimum the number must be. - */ - String min() default ""; - - /** - * @return The minimum number can be defined as an expression - */ - String minExpression() default ""; - - /** - * Integer property. - * - * @return The maximum number can be. - */ - String max() default ""; - - /** - * @return The maximum number can be defined as an expression - */ - String maxExpression() default ""; - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit='true' attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType type() default ValidatorType.FIELD; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/RegexFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/RegexFieldValidator.java deleted file mode 100644 index 94eea0b6d6..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/RegexFieldValidator.java +++ /dev/null @@ -1,182 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * Validates a string field using a regular expression. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
    regexyes The regex to validate the field value against.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @RegexFieldValidator( key = "regex.field", regex = "yourregexp")
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface RegexFieldValidator { - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * Regex used to evaluate field against it - * - * @return String regular expression - */ - String regex() default ""; - - /** - * Defines regex as an expression which first will be evaluated against the Value Stack to get proper regex. - * Thus allow to dynamically change regex base on user actions. - * - * @return String an expression which starts with '$' or '%' - */ - String regexExpression() default ""; - - /** - * To trim or not the value, default true - trim - * - * @return boolean trim or not the value before validation - */ - boolean trim() default true; - - /** - * Allows specify trim as an expression which will be evaluated during validation - * - * @return String an expression which starts with '$' or '%' - */ - String trimExpression() default ""; - - /** - * Match the value in case sensitive manner, default true - * - * @return boolean use case sensitive match or not - */ - boolean caseSensitive() default true; - - /** - * Allows specify caseSensitive as an expression which will be evaluated during validation - * - * @return boolean use case sensitive match or not - */ - String caseSensitiveExpression() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit='true' attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType type() default ValidatorType.FIELD; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/RequiredFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/RequiredFieldValidator.java deleted file mode 100644 index 900d5160be..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/RequiredFieldValidator.java +++ /dev/null @@ -1,134 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This validator checks that a field is non-null. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @RequiredFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
    - * 
    - * 
    - * - * - * @author Rainer Hermanns - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface RequiredFieldValidator { - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit="true" attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType type() default ValidatorType.FIELD; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/RequiredStringValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/RequiredStringValidator.java deleted file mode 100644 index b44ef0f325..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/RequiredStringValidator.java +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This validator checks that a String field is not empty (i.e. non-null with a length > 0). - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
    trim no true Boolean property. Determines whether the String is trimmed before performing the length check.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @RequiredStringValidator(message = "Default message", key = "i18n.key", shortCircuit = true, trim = true)
    - * 
    - * 
    - * - * - * @author Rainer Hermanns - * @version $Id$ - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface RequiredStringValidator { - - /** - * Boolean property. - * - * @return Determines whether the String is trimmed before performing the length check. - */ - boolean trim() default true; - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit="true" attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType type() default ValidatorType.FIELD; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ShortRangeFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ShortRangeFieldValidator.java deleted file mode 100644 index 6f779714f6..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ShortRangeFieldValidator.java +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This validator checks that a numeric field has a value within a specified range. - * If neither min nor max is set, nothing will be done. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
    min no   Short property. The minimum the number must be.
    minExpression no  OGNL expression used to obtain the minimum the number must be.
    max no   Short property. The maximum number can be.
    maxExpression no  OGNL expression used to obtain the maximum number can be.
    parsenofalseEnable parsing of min/max value.
    - * - *

    If neither min nor max is set, nothing will be done.

    - * - *

    The values for min and max must be inserted as String values so that "0" can be handled as a possible value.

    - * - * - *

    Example code:

    - * - *
    - * 
    - * @IntRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "0", max = "42")
    - *
    - * @IntRangeFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, min = "${minValue}", max = "${maxValue}" parse="true")
    - * 
    - * 
    - * - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface ShortRangeFieldValidator { - - /** - * Short property. - * - * @return The minimum the number must be. - */ - String min() default ""; - - /** - * @return The minimum the number must be defined as an expression. - */ - String minExpression() default ""; - - /** - * Short property. - * - * @return The maximum number can be. - */ - String max() default ""; - - /** - * @return The maximum number can be defined as an expression - */ - String maxExpression() default ""; - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit="true" attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType type() default ValidatorType.FIELD; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/StringLengthFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/StringLengthFieldValidator.java deleted file mode 100644 index 7d7d1ea623..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/StringLengthFieldValidator.java +++ /dev/null @@ -1,203 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This validator checks that a String field is of the right length. It assumes that the field is a String. - * If neither minLength nor maxLength is set, nothing will be done. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    typeyesValidatorType.FIELDEnum value from ValidatorType. Either FIELD or SIMPLE can be used here.
    trim no true Boolean property. Determines whether the String is trimmed before performing the length check.
    minLength no   Integer property. The minimum length the String must be.
    minLengthExpression no  OGNL expression used to obtain the minimum length the String must be.
    maxLength no   Integer property. The maximum length the String can be.
    maxLengthExpression no  OGNL expression used to obtain the maximum length the String can be.
    - * - *

    If neither minLength nor maxLength is set, nothing will be done.

    - * - * - * - *

    Example code:

    - * - *
    - * 
    - * @StringLengthFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, trim = true, minLength = "5",  maxLength = "12")
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface StringLengthFieldValidator { - - /** - * Boolean property. - * - * @return Determines whether the String is trimmed before performing the length check. - */ - boolean trim() default true; - - /** - * @return Determines whether the String is trimmed before performing the length check but defined as an expression - */ - String trimExpression() default ""; - - /** - * Integer property. - * - * @return The minimum length the String must be. - */ - String minLength() default ""; - - /** - * @return The minimum length the String must be defined as an expression - */ - String minLengthExpression() default ""; - - /** - * Integer property. - * - * @return The maximum length the String can be. - */ - String maxLength() default ""; - - /** - * @return The maximum length the String can be defined as an expression - */ - String maxLengthExpression() default ""; - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit="true" attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType[] type() default {ValidatorType.FIELD}; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java deleted file mode 100644 index 924770a07d..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/UrlValidator.java +++ /dev/null @@ -1,79 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * This validator checks that a field is a valid URL. - * - *
    - * @UrlValidator(message = "Default message", key = "i18n.key", shortCircuit = true)
    - * 
    - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface UrlValidator { - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit="true" attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; - - /** - * @return The validation type for this field/method. - */ - ValidatorType type() default ValidatorType.FIELD; - - /** - * @return Defines regex to use to validate url - */ - String urlRegex() default ""; - - /** - * @return Defines regex as an expression which will be evaluated to string and used to validate url - */ - String urlRegexExpression() default ""; - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/Validation.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/Validation.java deleted file mode 100644 index dd4ee6d5c2..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/Validation.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * This annotation has been deprecated since 2.1 as its previous purpose, to define classes that support annotation validations, - * is no longer necessary. - * - * - *

    Annotation usage:

    - * - * - *

    The Validation annotation must be applied at Type level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    validationsyes 
    - * - * - *

    Example code:

    - * - * An Annotated Interface - *
    - * 
    - * @Validation()
    - * public interface AnnotationDataAware {
    - *
    - *     void setBarObj(Bar b);
    - *
    - *     Bar getBarObj();
    - *
    - *     @RequiredFieldValidator(message = "You must enter a value for data.")
    - *     @RequiredStringValidator(message = "You must enter a value for data.")
    - *     void setData(String data);
    - *
    - *     String getData();
    - * }
    - * 
    - * 
    - * - *

    Example code:

    - * - * An Annotated Class - *
    - * 
    - * @Validation()
    - * public class SimpleAnnotationAction extends ActionSupport {
    - *
    - *     @RequiredFieldValidator(type = ValidatorType.FIELD, message = "You must enter a value for bar.")
    - *     @IntRangeFieldValidator(type = ValidatorType.FIELD, min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")
    - *     public void setBar(int bar) {
    - *         this.bar = bar;
    - *     }
    - *
    - *     public int getBar() {
    - *         return bar;
    - *     }
    - *
    - *     @Validations(
    - *             requiredFields =
    - *                     {@RequiredFieldValidator(type = ValidatorType.SIMPLE, fieldName = "customfield", message = "You must enter a value for field.")},
    - *             requiredStrings =
    - *                     {@RequiredStringValidator(type = ValidatorType.SIMPLE, fieldName = "stringisrequired", message = "You must enter a value for string.")},
    - *             emails =
    - *                     { @EmailValidator(type = ValidatorType.SIMPLE, fieldName = "emailaddress", message = "You must enter a value for email.")},
    - *             urls =
    - *                     { @UrlValidator(type = ValidatorType.SIMPLE, fieldName = "hreflocation", message = "You must enter a value for email.")},
    - *             stringLengthFields =
    - *                     {@StringLengthFieldValidator(type = ValidatorType.SIMPLE, trim = true, minLength="10" , maxLength = "12", fieldName = "needstringlength", message = "You must enter a stringlength.")},
    - *             intRangeFields =
    - *                     { @IntRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "intfield", min = "6", max = "10", message = "bar must be between ${min} and ${max}, current value is ${bar}.")},
    - *             dateRangeFields =
    - *                     {@DateRangeFieldValidator(type = ValidatorType.SIMPLE, fieldName = "datefield", min = "-1", max = "99", message = "bar must be between ${min} and ${max}, current value is ${bar}.")},
    - *             expressions = {
    - *                 @ExpressionValidator(expression = "foo > 1", message = "Foo must be greater than Bar 1. Foo = ${foo}, Bar = ${bar}."),
    - *                 @ExpressionValidator(expression = "foo > 2", message = "Foo must be greater than Bar 2. Foo = ${foo}, Bar = ${bar}."),
    - *                 @ExpressionValidator(expression = "foo > 3", message = "Foo must be greater than Bar 3. Foo = ${foo}, Bar = ${bar}."),
    - *                 @ExpressionValidator(expression = "foo > 4", message = "Foo must be greater than Bar 4. Foo = ${foo}, Bar = ${bar}."),
    - *                 @ExpressionValidator(expression = "foo > 5", message = "Foo must be greater than Bar 5. Foo = ${foo}, Bar = ${bar}.")
    - *     }
    - *     )
    - *     public String execute() throws Exception {
    - *         return SUCCESS;
    - *     }
    - * }
    - *
    - * 
    - * 
    - * - * @author Rainer Hermanns - * @deprecated Since Struts 2.1 because it isn't necessary anymore - */ -@Target({ElementType.TYPE}) -@Retention(RetentionPolicy.RUNTIME) -public @interface Validation { - - /** - * Used for class or interface validation rules. - * - * @return array of validations - */ - Validations[] validations() default {}; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ValidationParameter.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ValidationParameter.java deleted file mode 100644 index edfc24d611..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ValidationParameter.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * The ValidationParameter annotation is used as a parameter for CustomValidators. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must embedded into CustomValidator annotations as a parameter.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    nameyes parameter name.
    valueyes parameter value.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @CustomValidator(
    - *   type ="customValidatorName",
    - *   fieldName = "myField",
    - *   parameters = { @ValidationParameter( name = "paramName", value = "paramValue" ) }
    - * )
    - * 
    - * 
    - * - * @author jepjep - * @author Rainer Hermanns - */ -@Target( { ElementType.METHOD, ElementType.TYPE }) -@Retention(RetentionPolicy.RUNTIME) -public @interface ValidationParameter { - - String name(); - - String value(); - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ValidatorType.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ValidatorType.java deleted file mode 100644 index aed95d71fb..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/ValidatorType.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -/** - * ValidatorType - * - * @author Rainer Hermanns - * @version $Id$ - */ -public enum ValidatorType { - - FIELD, SIMPLE; - - @Override - public String toString() { - return super.toString().toUpperCase(); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/VisitorFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/VisitorFieldValidator.java deleted file mode 100644 index 5a63234412..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/VisitorFieldValidator.java +++ /dev/null @@ -1,165 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.annotations; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * - * The validator allows you to forward validator to object properties of your action - * using the objects own validator files. This allows you to use the ModelDriven development - * pattern and manage your validations for your models in one place, where they belong, next to - * your model classes. - * - * The VisitorFieldValidator can handle either simple Object properties, Collections of Objects, or Arrays. - * The error message for the VisitorFieldValidator will be appended in front of validator messages added - * by the validations for the Object message. - * - * - *

    Annotation usage:

    - * - * - *

    The annotation must be applied at method level.

    - * - * - *

    Annotation parameters:

    - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - * - *
    Parameter Required Default Notes
    messageyes field error message
    keyno i18n key from language specific properties file.
    messageParamsno Additional params to be used to customize message - will be evaluated against the Value Stack
    fieldNameno  
    shortCircuitnofalseIf this validator should be used as shortCircuit.
    context no action alias Determines the context to use for validating the Object property. If not defined, the context of the Action validation is propogated to the Object property validation. In the case of Action validation, this context is the Action alias.
    appendPrefix no true Determines whether the field name of this field validator should be prepended to the field name of the visited field to determine the full field name when an error occurs. For example, suppose that the bean being validated has a "name" property. If appendPrefix is true, then the field error will be stored under the field "bean.name". If appendPrefix is false, then the field error will be stored under the field "name".
    If you are using the VisitorFieldValidator to validate the model from a ModelDriven Action, you should set appendPrefix to false unless you are using "model.name" to reference the properties on your model.
    - * - * - *

    Example code:

    - * - *
    - * 
    - * @VisitorFieldValidator(message = "Default message", key = "i18n.key", shortCircuit = true, context = "action alias", appendPrefix = true)
    - * 
    - * 
    - * - * @author Rainer Hermanns - */ -@Target({ElementType.METHOD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface VisitorFieldValidator { - - /** - * Determines the context to use for validating the Object property. - * If not defined, the context of the Action validator is propagated to the Object property validator. - * In the case of Action validator, this context is the Action alias. - * - * @return context - */ - String context() default ""; - - /** - * Determines whether the field name of this field validator should be prepended to the field name of - * the visited field to determine the full field name when an error occurs. For example, suppose that - * the bean being validated has a "name" property. - * - * If appendPrefix is true, then the field error will be stored under the field "bean.name". - * If appendPrefix is false, then the field error will be stored under the field "name". - * - * If you are using the VisitorFieldValidator to validate the model from a ModelDriven Action, - * you should set appendPrefix to false unless you are using "model.name" to reference the properties - * on your model. - * - * @return true if append prefix - */ - boolean appendPrefix() default true; - - /** - * @return The default error message for this validator. - * NOTE: It is required to set a message, if you are not using the message key for 18n lookup! - */ - String message() default ""; - - /** - * @return The message key to lookup for i18n. - */ - String key() default ""; - - /** - * @return The optional fieldName for SIMPLE validator types. - */ - String fieldName() default ""; - - /** - * @return Additional params to be used to customize message - will be evaluated against the Value Stack - */ - String[] messageParams() default {}; - - /** - * If this is activated, the validator will be used as short-circuit. - * - * Adds the short-circuit="true" attribute value if true. - * - * @return true if validator will be used as short-circuit. Default is false. - */ - boolean shortCircuit() default false; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/package.html b/core/src/main/java/com/opensymphony/xwork2/validator/annotations/package.html deleted file mode 100644 index ff910e7886..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/annotations/package.html +++ /dev/null @@ -1 +0,0 @@ -Validator annotations. diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/package.html b/core/src/main/java/com/opensymphony/xwork2/validator/package.html deleted file mode 100644 index 07e7894e57..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/package.html +++ /dev/null @@ -1 +0,0 @@ -XWork validation subsystem. \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/ConditionalVisitorFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/ConditionalVisitorFieldValidator.java deleted file mode 100644 index 7e92f3fc32..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/ConditionalVisitorFieldValidator.java +++ /dev/null @@ -1,84 +0,0 @@ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.validator.ValidationException; - -/** - * - * The ConditionalVisitorFieldValidator will forward validation to the VisitorFieldValidator - * only if the expression will evaluate to true. - * - * - * - *
      - *
    • expression - an OGNL expression which should evaluate to true to pass validation to the VisitorFieldValidator
    • - *
    - * - * - *
    - * 
    - * <field name="colleaguePosition">
    - *     <field-validator type="conditionalvisitor">
    - *         <param name="expression">reason == 'colleague' and colleaguePositionID == 'OTHER'</param>
    - *         <message>You must select reason Colleague and position Other</message>
    - *     </field-validator>
    - * </field>
    - * 
    - * 
    - * - * @author Matt Raible - */ -public class ConditionalVisitorFieldValidator extends VisitorFieldValidator { - - private String expression; - - public void setExpression(String expression) { - this.expression = expression; - } - - public String getExpression() { - return expression; - } - - /** - * If expression evaluates to true, invoke visitor validation. - * - * @param object the object being validated - * @throws ValidationException in case of validation problems - */ - @Override - public void validate(Object object) throws ValidationException { - if (validateExpression(object)) { - super.validate(object); - } - } - - /** - * Validate the expression contained in the "expression" paramter. - * - * @param object the object you're validating - * @return true if expression evaluates to true (implying a validation - * failure) - * @throws ValidationException if anything goes wrong - */ - public boolean validateExpression(Object object) throws ValidationException { - Boolean answer = Boolean.FALSE; - Object obj = null; - - try { - obj = getFieldValue(expression, object); - } catch (ValidationException e) { - throw e; - } catch (Exception e) { - // let this pass, but it will be logged right below - } - - if ((obj != null) && (obj instanceof Boolean)) { - answer = (Boolean) obj; - } else { - log.warn("Got result of {} when trying to get Boolean.", obj); - } - - return answer; - } - -} \ No newline at end of file diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/ConversionErrorFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/ConversionErrorFieldValidator.java deleted file mode 100644 index 6c49380953..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/ConversionErrorFieldValidator.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.conversion.impl.XWorkConverter; -import com.opensymphony.xwork2.validator.ValidationException; -import org.apache.commons.lang3.StringUtils; - -import java.util.Map; - - -/** - * - * Field Validator that checks if a conversion error occurred for this field. - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    - * - * - * - *
    - *     <!-- Plain Validator Syntax -->
    - *     <validator type="conversion">
    - *     		<param name="fieldName">myField</param>
    - *          <message>Conversion Error Occurred</message>
    - *     </validator>
    - *      
    - *     <!-- Field Validator Syntax -->
    - *     <field name="myField">
    - *        <field-validator type="conversion">
    - *           <message>Conversion Error Occurred</message>
    - *        </field-validator>
    - *     </field>
    - * 
    - * - * - * @author Jason Carreira - * @author tm_jee - */ -public class ConversionErrorFieldValidator extends RepopulateConversionErrorFieldValidatorSupport { - - /** - * The validation implementation must guarantee that setValidatorContext will - * be called with a non-null ValidatorContext before validate is called. - * - * @param object the object to be validated - * @throws ValidationException in case of validation problems - */ - @Override - public void doValidate(Object object) throws ValidationException { - String fieldName = getFieldName(); - String fullFieldName = getValidatorContext().getFullFieldName(fieldName); - ActionContext context = ActionContext.getContext(); - Map conversionErrors = context.getConversionErrors(); - - if (conversionErrors.containsKey(fullFieldName)) { - if (StringUtils.isBlank(defaultMessage)) { - defaultMessage = XWorkConverter.getConversionErrorMessage(fullFieldName, context.getValueStack()); - } - - addFieldError(fieldName, object); - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidator.java deleted file mode 100644 index 0adbc5c3e4..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidator.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import java.util.Date; - -/** - * - * - * Field Validator that checks if the date supplied is within a specific range. - * - * NOTE: If no date converter is specified, XWorkBasicConverter will kick - * in to do the date conversion, which by default using the Date.SHORT format using - * the a problematically specified locale else falling back to the system - * default locale. - * - * - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    • min - the min date range. If not specified will not be checked.
    • - *
    • max - the max date range. If not specified will not be checked.
    • - *
    • parse - if set to true, minExpression and maxExpression will be evaluated to find min/max
    • - *
    • minExpression - expression to calculate the minimum value (if none is specified, it will not be checked)
    • - *
    • maxExpression - expression to calculate the maximum value (if none is specified, it will not be checked)
    • - *
    - * - * You can either use the min / max value or minExpression / maxExpression (when parse is set to true) - - * using expression can be slightly slower, see the example below. - * - * - * - * Do not use ${minExpression} and ${maxExpression} as an expression as this will turn into infinitive loop! - * - * - *
    - * 
    - * <validators>
    - *     <!-- Plain Validator syntax -->
    - *     <validator type="date">
    - *         <param name="fieldName">birthday</param>
    - *         <param name="min">01/01/1990</param>
    - *         <param name="max">01/01/2000</param>
    - *         <message>Birthday must be within ${min} and ${max}</message>
    - *     </validator>
    - *
    - *     <!-- Field Validator Syntax -->
    - *     <field name="birthday">
    - *         <field-validator type="date">
    - *      	   <param name="min">01/01/1990</param>
    - *             <param name="max">01/01/2000</param>
    - *             <message>Birthday must be within ${min} and ${max}</message>
    - *     	   </field>
    - *     </field>
    - *
    - *     <!-- Field Validator Syntax with expression -->
    - *     <field name="birthday">
    - *         <field-validator type="date">
    - *             <param name="minExpression">${minValue}</param> <!-- will be evaluated as: Date getMinValue() -->
    - *             <param name="maxExpression">${maxValue}</param> <!-- will be evaluated as: Date getMaxValue() -->
    - *             <message>Age needs to be between ${min} and ${max}</message>
    - *         </field-validator>
    - *     </field>
    - * </validators>
    - * 
    - * 
    - * - * - * @author Jason Carreira - */ -public final class DateRangeFieldValidator extends RangeValidatorSupport { - - public DateRangeFieldValidator() { - super(Date.class); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/DoubleRangeFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/DoubleRangeFieldValidator.java deleted file mode 100644 index 8ed4e4c1b8..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/DoubleRangeFieldValidator.java +++ /dev/null @@ -1,194 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.validator.ValidationException; -import org.apache.commons.lang3.StringUtils; - -/** - * - * Field Validator that checks if the double specified is within a certain range. - * - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    • minInclusive - the minimum inclusive value in FloatValue format specified by Java language (if none is specified, it will not be checked)
    • - *
    • maxInclusive - the maximum inclusive value in FloatValue format specified by Java language (if none is specified, it will not be checked)
    • - *
    • minExclusive - the minimum exclusive value in FloatValue format specified by Java language (if none is specified, it will not be checked)
    • - *
    • maxExclusive - the maximum exclusive value in FloatValue format specified by Java language (if none is specified, it will not be checked)
    • - *
    • minInclusiveExpression - the minimum inclusive value specified as a OGNL expression (if none is specified, it will not be checked)
    • - *
    • maxInclusiveExpression - the maximum inclusive value specified as a OGNL expression (if none is specified, it will not be checked)
    • - *
    • minExclusiveExpression - the minimum exclusive value specified as a OGNL expression (if none is specified, it will not be checked)
    • - *
    • maxExclusiveExpression - the maximum exclusive value specified as a OGNL expression (if none is specified, it will not be checked)
    • - *
    - * - * You can specify either minInclusive, maxInclusive, minExclusive and maxExclusive or minInclusiveExpression, maxInclusiveExpression, - * minExclusiveExpression and maxExclusiveExpression as a OGNL expression, see example below. You can always try to mix params - * but be aware that such behaviour was not tested. - * - * - * - * - * Do not use ${minInclusiveExpression}, ${maxInclusiveExpression}, ${minExclusiveExpressionExpression} and ${maxExclusive} - * as an expression as this will turn into infinitive loop! - * - * - * - *
    - * 
    - * <validators>
    - *     <!-- Plain Validator Syntax -->
    - *         <validator type="double">
    - *         <param name="fieldName">percentage</param>
    - *         <param name="minInclusive">20.1</param>
    - *         <param name="maxInclusive">50.1</param>
    - *         <message>Age needs to be between ${minInclusive} and ${maxInclusive} (inclusive)</message>
    - *     </validator>
    - *
    - *     <!-- Field Validator Syntax -->
    - *     <field name="percentage">
    - *         <field-validator type="double">
    - *             <param name="minExclusive">0.123</param>
    - *             <param name="maxExclusive">99.98</param>
    - *             <message>Percentage needs to be between ${minExclusive} and ${maxExclusive} (exclusive)</message>
    - *         </field-validator>
    - *     </field>
    - *
    - *     <!-- Field Validator Syntax with expression -->
    - *     <field name="percentage">
    - *         <field-validator type="double">
    - *             <param name="minExclusiveExpression">${minExclusiveValue}</param> <!-- will be evaluated as: Double getMinExclusiveValue() -->
    - *             <param name="maxExclusiveExpression">${maxExclusiveValue}</param> <!-- will be evaluated as: Double getMaxExclusiveValue() -->
    - *             <message>Percentage needs to be between ${minExclusive} and ${maxExclusive} (exclusive)</message>
    - *         </field-validator>
    - *     </field>
    - * </validators>
    - * 
    - * 
    - * - * @author Rainer Hermanns - * @author Rene Gielen - */ -public class DoubleRangeFieldValidator extends FieldValidatorSupport { - - private Double maxInclusive = null; - private Double minInclusive = null; - private Double minExclusive = null; - private Double maxExclusive = null; - - private String minInclusiveExpression; - private String maxInclusiveExpression; - private String minExclusiveExpression; - private String maxExclusiveExpression; - - public void validate(Object object) throws ValidationException { - String fieldName = getFieldName(); - Double value; - try { - Object obj = this.getFieldValue(fieldName, object); - if (obj == null) { - return; - } - value = Double.valueOf(obj.toString()); - } catch (NumberFormatException e) { - return; - } - - Double maxInclusiveToUse = getMaxInclusive(); - Double minInclusiveToUse = getMinInclusive(); - Double maxExclusiveToUse = getMaxExclusive(); - Double minExclusiveToUse = getMinExclusive(); - - if ((maxInclusiveToUse != null && value.compareTo(maxInclusiveToUse) > 0) || - (minInclusiveToUse != null && value.compareTo(minInclusiveToUse) < 0) || - (maxExclusiveToUse != null && value.compareTo(maxExclusiveToUse) >= 0) || - (minExclusiveToUse != null && value.compareTo(minExclusiveToUse) <= 0)) { - addFieldError(fieldName, object); - } - } - - public void setMaxInclusive(Double maxInclusive) { - this.maxInclusive = maxInclusive; - } - - public Double getMaxInclusive() { - if (maxInclusive != null) { - return maxInclusive; - } else if (StringUtils.isNotEmpty(maxInclusiveExpression)) { - return (Double) parse(maxInclusiveExpression, Double.class); - } - return maxInclusive; - } - - public void setMinInclusive(Double minInclusive) { - this.minInclusive = minInclusive; - } - - public Double getMinInclusive() { - if (minInclusive != null) { - return minInclusive; - } else if (StringUtils.isNotEmpty(minInclusiveExpression)) { - return (Double) parse(minInclusiveExpression, Double.class); - } - return null; - } - - public void setMinExclusive(Double minExclusive) { - this.minExclusive = minExclusive; - } - - public Double getMinExclusive() { - if (minExclusive != null) { - return minExclusive; - } else if (StringUtils.isNotEmpty(minExclusiveExpression)) { - return (Double) parse(minExclusiveExpression, Double.class); - } - return null; - } - - public void setMaxExclusive(Double maxExclusive) { - this.maxExclusive = maxExclusive; - } - - public Double getMaxExclusive() { - if (maxExclusive != null) { - return maxExclusive; - } else if (StringUtils.isNotEmpty(maxExclusiveExpression)) { - return (Double) parse(maxExclusiveExpression, Double.class); - } - return null; - } - - public void setMinInclusiveExpression(String minInclusiveExpression) { - this.minInclusiveExpression = minInclusiveExpression; - } - - public void setMaxInclusiveExpression(String maxInclusiveExpression) { - this.maxInclusiveExpression = maxInclusiveExpression; - } - - public void setMinExclusiveExpression(String minExclusiveExpression) { - this.minExclusiveExpression = minExclusiveExpression; - } - - public void setMaxExclusiveExpression(String maxExclusiveExpression) { - this.maxExclusiveExpression = maxExclusiveExpression; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/EmailValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/EmailValidator.java deleted file mode 100644 index 98958a0a8e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/EmailValidator.java +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - - -/** - * - * EmailValidator checks that a given String field, if not empty, is a valid email address. - * - * The regular expression used to validate that the string is an email address is: - * - *
    - * \\b^['_a-z0-9-\\+]+(\\.['_a-z0-9-\\+]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,6})$\\b
    - * 
    - * - * You can also specify expression, caseSensitive and trim params as a OGNL expression, see the example below. - * - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    - * Check also documentation of the RegexpValidator for more details - the EmailValidator bases on it. - * - * - * - * Do not use ${regexExpression}, ${caseSensitiveExpression} and ${trimExpression} as an expression as this will turn into infinitive loop! - * - * - *
    - * 
    - *     <!-- Plain Validator Syntax -->
    - *     <validators>
    - *         <validator type="email">
    - *             <param name="fieldName">myEmail</param>
    - *             <message>Must provide a valid email</message>
    - *         </validator>
    - *     </validators>
    - *     
    - *     <!-- Field Validator Syntax -->
    - *     <field name="myEmail">
    - *        <field-validator type="email">
    - *           <message>Must provide a valid email</message>
    - *        </field-validator>
    - *     </field>
    - *
    - *     <!-- Field Validator Syntax with expressions -->
    - *     <!-- Only available when used with xml based configuration, if you want to have the same
    - *             flexibility with annotations use @RegexFieldValidator instead -->
    - *     <field name="myEmail">
    - *        <field-validator type="email">
    - *           <param name="regexExpression">${emailPattern}</param> <!-- will be evaluated as: String getEmailPattern() -->
    - *           <param name="caseSensitiveExpression">${emailCaseSensitive}</param> <!-- will be evaluated as: boolean getEmailCaseSensitive() -->
    - *           <param name="trimExpression">${trimEmail}</param> <!-- will be evaluated as: boolean getTrimEmail() -->
    - *           <message>Must provide a valid email</message>
    - *        </field-validator>
    - *     </field>
    - * 
    - * 
    - * - * @author jhouse - * @author tm_jee - * @version $Date$ $Id$ - */ -public class EmailValidator extends RegexFieldValidator { - - public static final String EMAIL_ADDRESS_PATTERN = "\\b^['_a-z0-9-\\+]+(\\.['_a-z0-9-\\+]+)*@[a-z0-9-]+(\\.[a-z0-9-]+)*\\.([a-z]{2,6})$\\b"; - - public EmailValidator() { - setRegex(EMAIL_ADDRESS_PATTERN); - setCaseSensitive(false); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/ExpressionValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/ExpressionValidator.java deleted file mode 100644 index 6e59af200e..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/ExpressionValidator.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.validator.ValidationException; - -/** - * - * A Non-Field Level validator that validates based on regular expression supplied. - * - * - * - *
      - *
    • expression - the Ognl expression to be evaluated against the stack (Must evaluate to a Boolean)
    • - *
    - * - * - * - *
    - * 
    - *     <validators>
    - *           <validator type="expression">
    - *              <param name="expression"> .... </param>
    - *              <message>Failed to meet Ognl Expression  .... </message>
    - *           </validator>
    - *     </validators>
    - * 
    - * 
    - * - * @author Jason Carreira - */ -public class ExpressionValidator extends ValidatorSupport { - - private String expression; - - public void setExpression(String expression) { - this.expression = expression; - } - - public String getExpression() { - return expression; - } - - public void validate(Object object) throws ValidationException { - Boolean answer = Boolean.FALSE; - Object obj = null; - - try { - obj = getFieldValue(expression, object); - } catch (ValidationException e) { - throw e; - } catch (Exception e) { - // let this pass, but it will be logged right below - } - - if ((obj != null) && (obj instanceof Boolean)) { - answer = (Boolean) obj; - } else { - log.warn("Got result of [{}] when trying to get Boolean.", obj); - } - - if (!answer) { - log.debug("Validation failed on expression [{}] with validated object [{}]", expression, object); - addActionError(object); - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/FieldExpressionValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/FieldExpressionValidator.java deleted file mode 100644 index 12dd7c5754..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/FieldExpressionValidator.java +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.validator.ValidationException; - - -/** - * - * Validates a field using an OGNL expression. - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    • expression - The Ognl expression (must evaluate to a boolean) which is to be evalidated the stack
    • - *
    - * - * - *
    - * 
    - *    <!-- Plain Validator Syntax -->
    - *    <validators>
    - *        <!-- Plain Validator Syntax -->
    - *        <validator type="fieldexpression">
    - *           <param name="fieldName">myField</param>
    - *           <param name="expression"><![CDATA[#myCreditLimit > #myGirfriendCreditLimit]]></param>
    - *           <message>My credit limit should be MORE than my girlfriend</message>
    - *        <validator>
    - *        
    - *        <!-- Field Validator Syntax -->
    - *        <field name="myField">
    - *            <field-validator type="fieldexpression">
    - *                <param name="expression"><![CDATA[#myCreditLimit > #myGirfriendCreditLimit]]></param>
    - *                <message>My credit limit should be MORE than my girlfriend</message>
    - *            </field-validator>
    - *        </field>
    - *        
    - *    </vaidators>
    - * 
    - * 
    - */ -public class FieldExpressionValidator extends FieldValidatorSupport { - - private String expression; - - public void setExpression(String expression) { - this.expression = expression; - } - - public String getExpression() { - return expression; - } - - public void validate(Object object) throws ValidationException { - String fieldName = getFieldName(); - - Boolean answer = Boolean.FALSE; - Object obj = null; - - try { - obj = getFieldValue(expression, object); - } catch (ValidationException e) { - throw e; - } catch (Exception e) { - // let this pass, but it will be logged right below - } - - if ((obj != null) && (obj instanceof Boolean)) { - answer = (Boolean) obj; - } else { - log.warn("Got result of {} when trying to get Boolean.", obj); - } - - if (!answer.booleanValue()) { - addFieldError(fieldName, object); - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/FieldValidatorSupport.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/FieldValidatorSupport.java deleted file mode 100644 index 4a3f147dc7..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/FieldValidatorSupport.java +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.validator.FieldValidator; - - -/** - * Base class for field validators. - * - * @author Jason Carreira - */ -public abstract class FieldValidatorSupport extends ValidatorSupport implements FieldValidator { - - private String fieldName; - private String type; - - public void setFieldName(String fieldName) { - this.fieldName = fieldName; - } - - public String getFieldName() { - return fieldName; - } - - @Override - public void setValidatorType(String type) { - this.type = type; - } - - @Override - public String getValidatorType() { - return type; - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/IntRangeFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/IntRangeFieldValidator.java deleted file mode 100644 index 0f1c82f2a6..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/IntRangeFieldValidator.java +++ /dev/null @@ -1,83 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -/** - * - * Field Validator that checks if the integer specified is within a certain range. - * - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    • min - the minimum value (if none is specified, it will not be checked)
    • - *
    • max - the maximum value (if none is specified, it will not be checked)
    • - *
    • parse - if set to true, minExpression and maxExpression will be evaluated to find min/max
    • - *
    • minExpression - expression to calculate the minimum value (if none is specified, it will not be checked)
    • - *
    • maxExpression - expression to calculate the maximum value (if none is specified, it will not be checked)
    • - *
    - * - * You can either use the min / max value or minExpression / maxExpression (when parse is set to true) - - * using expression can be slightly slower, see the example below. - * - * - * - * Do not use ${minExpression} and ${maxExpression} as an expression as this will turn into infinitive loop! - * - * - *
    - * 
    - * <validators>
    - *      <!-- Plain Validator Syntax -->
    - *      <validator type="int">
    - *          <param name="fieldName">age</param>
    - *          <param name="min">20</param>
    - *          <param name="max">50</param>
    - *          <message>Age needs to be between ${min} and ${max}</message>
    - *      </validator>
    - *
    - *      <!-- Field Validator Syntax -->
    - *      <field name="age">
    - *          <field-validator type="int">
    - *              <param name="min">20</param>
    - *              <param name="max">50</param>
    - *              <message>Age needs to be between ${min} and ${max}</message>
    - *          </field-validator>
    - *      </field>
    - *
    - *      <!-- Field Validator Syntax with expression -->
    - *      <field name="age">
    - *          <field-validator type="int">
    - *              <param name="minExpression">${minValue}</param> <!-- will be evaluated as: Integer getMinValue() -->
    - *              <param name="maxExpression">${maxValue}</param> <!-- will be evaluated as: Integer getMaxValue() -->
    - *              <message>Age needs to be between ${min} and ${max}</message>
    - *          </field-validator>
    - *      </field>
    - * </validators>
    - * 
    - * 
    - * - * @author Jason Carreira - * @version $Date$ $Id$ - */ -public final class IntRangeFieldValidator extends RangeValidatorSupport { - - public IntRangeFieldValidator() { - super(Integer.class); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/LongRangeFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/LongRangeFieldValidator.java deleted file mode 100644 index 7c2999aed4..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/LongRangeFieldValidator.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -/** - * - * Field Validator that checks if the long specified is within a certain range. - * - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    • min - the minimum value (if none is specified, it will not be checked)
    • - *
    • max - the maximum value (if none is specified, it will not be checked)
    • - *
    • parse - if set to true, minExpression and maxExpression will be evaluated to find min/max
    • - *
    • minExpression - expression to calculate the minimum value (if none is specified, it will not be checked)
    • - *
    • maxExpression - expression to calculate the maximum value (if none is specified, it will not be checked)
    • - *
    - * - * You can either use the min / max value or minExpression / maxExpression (when parse is set to true) - - * using expression can be slightly slower, see the example below. - * - * - * - * Do not use ${minExpression} and ${maxExpression} as an expression as this will turn into infinitive loop! - * - * - *
    - * 
    - * 	<validators>
    - *      <!-- Plain Validator Syntax -->
    - *      <validator type="long">
    - *          <param name="fieldName">age</param>
    - *          <param name="min">20</param>
    - *          <param name="max">50</param>
    - *          <message>Age needs to be between ${min} and ${max}</message>
    - *      </validator>
    - *
    - *      <!-- Field Validator Syntax -->
    - *      <field name="age">
    - *          <field-validator type="long">
    - *              <param name="min">20</param>
    - *              <param name="max">50</param>
    - *              <message>Age needs to be between ${min} and ${max}</message>
    - *          </field-validator>
    - *      </field>
    - *
    - *      <!-- Field Validator Syntax with expression -->
    - *      <field name="age">
    - *          <field-validator type="long">
    - *              <param name="minExpression">${minValue}</param> <!-- will be evaluated as: Long getMinValue() -->
    - *              <param name="maxExpression">${maxValue}</param> <!-- will be evaluated as: Long getMaxValue() -->
    - *              <message>Age needs to be between ${min} and ${max}</message>
    - *          </field-validator>
    - *      </field>
    - * </validators>
    - * 
    - * 
    - * - * @version $Date$ - */ -public final class LongRangeFieldValidator extends RangeValidatorSupport { - - public LongRangeFieldValidator() { - super(Long.class); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RangeValidatorSupport.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/RangeValidatorSupport.java deleted file mode 100644 index 39c0e865d6..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RangeValidatorSupport.java +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; -import com.opensymphony.xwork2.validator.ValidationException; -import org.apache.commons.lang3.StringUtils; - -/** - * Base class for range based validators. Use this class to develop any other custom range validators. - */ -public abstract class RangeValidatorSupport extends FieldValidatorSupport { - - private static final Logger LOG = LogManager.getLogger(RangeValidatorSupport.class); - - private final Class type; - - private T min; - private String minExpression; - private T max; - private String maxExpression; - - protected RangeValidatorSupport(Class type) { - this.type = type; - } - - public void validate(Object object) throws ValidationException { - Object obj = getFieldValue(getFieldName(), object); - Comparable value = (Comparable) obj; - - // if there is no value - don't do comparison - // if a value is required, a required validator should be added to the field - if (value == null) { - return; - } - - // only check for a minimum value if the min parameter is set - T minComparatorValue = getMin(); - if ((minComparatorValue != null) && (value.compareTo(minComparatorValue) < 0)) { - addFieldError(getFieldName(), object); - } - - // only check for a maximum value if the max parameter is set - T maxComparatorValue = getMax(); - if ((maxComparatorValue != null) && (value.compareTo(maxComparatorValue) > 0)) { - addFieldError(getFieldName(), object); - } - } - - public void setMin(T min) { - this.min = min; - } - - public T getMin() { - if (min != null) { - return min; - } else if (StringUtils.isNotEmpty(minExpression)) { - return (T) parse(minExpression, type); - } else { - return null; - } - } - - public void setMinExpression(String minExpression) { - LOG.debug("${minExpression} was defined as [{}]", minExpression); - this.minExpression = minExpression; - } - - public void setMax(T max) { - this.max = max; - } - - public T getMax() { - if (max != null) { - return max; - } else if (StringUtils.isNotEmpty(maxExpression)) { - return (T) parse(maxExpression, type); - } else { - return null; - } - } - - public void setMaxExpression(String maxExpression) { - LOG.debug("${maxExpression} was defined as [{}]", maxExpression); - this.maxExpression = maxExpression; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RegexFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/RegexFieldValidator.java deleted file mode 100644 index b931482827..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RegexFieldValidator.java +++ /dev/null @@ -1,219 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ - -package com.opensymphony.xwork2.validator.validators; - -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; -import com.opensymphony.xwork2.validator.ValidationException; -import org.apache.commons.lang3.StringUtils; - -import java.util.regex.Matcher; -import java.util.regex.Pattern; - -/** - * - * Validates a string field using a regular expression. - * - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    • regexp - The RegExp expression
    • - *
    • caseSensitive - Boolean (Optional). Sets whether the expression should be matched against in a case-sensitive way. Default is true.
    • - *
    • trim - Boolean (Optional). Sets whether the expression should be trimmed before matching. Default is true.
    • - *
    • regexExpression - String (Optional). Defines regExp expression as an OGNL expression - will be evaluated to String
    • - *
    • caseSensitiveExpression - String (Optional). Defines caseSensitive param as an OGNL expression - will be evaluated to Boolean.
    • - *
    • trimExpression - String (Optional). Defines trim param as an OGNL expression - will be evaluated to Boolean
    • - *
    - * - *

    - * You can mix normal params with expression aware params but thus was not tested - *

    - * - * - * - *

    - * Do not use ${regexExpression}, ${caseSensitiveExpression} and ${trimExpression} as an expression as this will turn into infinitive loop! - *

    - * - * - *
    - * 
    - * <validators>
    - *     <!-- Plain Validator Syntax -->
    - *     <validator type="regex">
    - *         <param name="fieldName">myStrangePostcode</param>
    - *         <param name="regex"><![CDATA[([aAbBcCdD][123][eEfFgG][456])]]></param>
    - *     </validator>
    - *
    - *     <!-- Field Validator Syntax -->
    - *     <field name="myStrangePostcode">
    - *         <field-validator type="regex">
    - *             <param name="regex"><![CDATA[([aAbBcCdD][123][eEfFgG][456])]]></param>
    - *         </field-validator>
    - *     </field>
    - *
    - *     <!-- Field Validator Syntax with expressions -->
    - *     <field name="myStrangePostcode">
    - *         <field-validator type="regex">
    - *             <param name="regexExpression">${regexValue}</param> <!-- will be evaluated as: String getRegexValue() -->
    - *             <param name="caseSensitiveExpression">${caseSensitiveValue}</param> <!-- will be evaluated as: boolean getCaseSensitiveValue() -->
    - *             <param name="trimExpression">${trimValue}</param> <!-- will be evaluated as: boolean getTrimValue() -->
    - *         </field-validator>
    - *     </field>
    - * </validators>
    - * 
    - * 
    - * - * @author Quake Wang - */ -public class RegexFieldValidator extends FieldValidatorSupport { - - private static final Logger LOG = LogManager.getLogger(RegexFieldValidator.class); - - private String regex; - private String regexExpression; - private Boolean caseSensitive = true; - private String caseSensitiveExpression = ""; - private Boolean trim = true; - private String trimExpression = ""; - - public void validate(Object object) throws ValidationException { - String fieldName = getFieldName(); - Object value = this.getFieldValue(fieldName, object); - // if there is no value - don't do comparison - // if a value is required, a required validator should be added to the field - String regexToUse = getRegex(); - LOG.debug("Defined regexp as [{}]", regexToUse); - - if (value == null || regexToUse == null) { - return; - } - - // XW-375 - must be a string - if (!(value instanceof String)) { - return; - } - - // string must not be empty - String str = ((String) value).trim(); - if (str.length() == 0) { - return; - } - - // match against expression - Pattern pattern; - if (isCaseSensitive()) { - pattern = Pattern.compile(regexToUse); - } else { - pattern = Pattern.compile(regexToUse, Pattern.CASE_INSENSITIVE); - } - - String compare = (String) value; - if ( isTrimed() ) { - compare = compare.trim(); - } - Matcher matcher = pattern.matcher( compare ); - - if (!matcher.matches()) { - addFieldError(fieldName, object); - } - } - - /** - * @return Returns the regular expression to be matched. - */ - public String getRegex() { - if (StringUtils.isNotEmpty(regex)) { - return regex; - } else if (StringUtils.isNotEmpty(regexExpression)) { - return (String) parse(regexExpression, String.class); - } else { - return null; - } - } - - /** - * @param regex the regular expression to be matched - */ - public void setRegex(String regex) { - this.regex = regex; - } - - /** - * @param regexExpression the regular expression as an OGNL expression to be matched - */ - public void setRegexExpression(String regexExpression) { - this.regexExpression = regexExpression; - } - - /** - * @return Returns whether the expression should be matched against in - * a case-sensitive way. Default is true. - */ - public boolean isCaseSensitive() { - if (StringUtils.isNotEmpty(caseSensitiveExpression)) { - return (Boolean) parse(caseSensitiveExpression, Boolean.class); - } - return caseSensitive; - } - - /** - * @param caseSensitive whether the expression should be matched against in - * a case-sensitive way. Default is true. - */ - public void setCaseSensitive(Boolean caseSensitive) { - this.caseSensitive = caseSensitive; - } - - /** - * @param caseSensitiveExpression Allows specify caseSensitive param as an OGNL expression - */ - public void setCaseSensitiveExpression(String caseSensitiveExpression) { - this.caseSensitiveExpression = caseSensitiveExpression; - } - - /** - * @return Returns whether the expression should be trimed before matching. - * Default is true. - */ - public boolean isTrimed() { - if (StringUtils.isNotEmpty(trimExpression)) { - return (Boolean) parse(trimExpression, Boolean.class); - } - return trim; - } - - /** - * @param trim whether the expression should be trimed before matching. - * Default is true. - */ - public void setTrim(Boolean trim) { - this.trim = trim; - } - - /** - * Allows specify trim param as an OGNL expression - * - * @param trimExpression trim param as an OGNL expression - */ - public void setTrimExpression(String trimExpression) { - this.trimExpression = trimExpression; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RepopulateConversionErrorFieldValidatorSupport.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/RepopulateConversionErrorFieldValidatorSupport.java deleted file mode 100644 index af0edf3d42..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RepopulateConversionErrorFieldValidatorSupport.java +++ /dev/null @@ -1,199 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.interceptor.PreResultListener; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.validator.ValidationException; -import org.apache.commons.lang3.StringEscapeUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.LinkedHashMap; -import java.util.Map; - -/** - *

    - * An abstract base class that adds in the capability to populate the stack with - * a fake parameter map when a conversion error has occurred and the 'repopulateField' - * property is set to "true". - *

    - * - * - *

    - * The capability of auto-repopulating the stack with a fake parameter map when - * a conversion error has occurred can be done with 'repopulateField' property - * set to "true". - *

    - * - *

    - * This is typically useful when one wants to repopulate the field with the original value - * when a conversion error occurred. Eg. with a textfield that only allows an Integer - * (the action class have an Integer field declared), upon conversion error, the incorrectly - * entered integer (maybe a text 'one') will not appear when dispatched back. With 'repopulateField' - * property set to true, it will, meaning the textfield will have 'one' as its value - * upon conversion error. - *

    - * - * - - * - *
    - * 
    - *
    - * <!-- myJspPage.jsp -->
    - * <ww:form action="someAction" method="POST">
    - *   ....
    - *   <ww:textfield
    - *       label="My Integer Field"
    - *       name="myIntegerField" />
    - *   ....
    - *   <ww:submit />
    - * </ww:form>
    - *
    - * 
    - * 
    - * - *
    - * 
    - *
    - * <!-- xwork.xml -->
    - * <xwork>
    - * <include file="xwork-default.xml" />
    - * ....
    - * <package name="myPackage" extends="xwork-default">
    - *   ....
    - *   <action name="someAction" class="example.MyActionSupport.java">
    - *      <result name="input">myJspPage.jsp</result>
    - *      <result>success.jsp</result>
    - *   </action>
    - *   ....
    - * </package>
    - * ....
    - * </xwork>
    - *
    - * 
    - * 
    - * - * - *
    - * 
    - *
    - * <!-- MyActionSupport.java -->
    - * public class MyActionSupport extends ActionSupport {
    - *    private Integer myIntegerField;
    - *
    - *    public Integer getMyIntegerField() { return this.myIntegerField; }
    - *    public void setMyIntegerField(Integer myIntegerField) {
    - *       this.myIntegerField = myIntegerField;
    - *    }
    - * }
    - *
    - * 
    - * 
    - * - * - *
    - * 
    - *
    - * <!-- MyActionSupport-someAction-validation.xml -->
    - * <validators>
    - *   ...
    - *   <field name="myIntegerField">
    - *      <field-validator type="conversion">
    - *         <param name="repopulateField">true</param>
    - *         <message>Conversion Error (Integer Wanted)</message>
    - *      </field-validator>
    - *   </field>
    - *   ...
    - * </validators>
    - *
    - * 
    - * 
    - * - * @author tm_jee - */ -public abstract class RepopulateConversionErrorFieldValidatorSupport extends FieldValidatorSupport { - - private static final Logger LOG = LogManager.getLogger(RepopulateConversionErrorFieldValidatorSupport.class); - - private boolean repopulateField = false; - - public boolean isRepopulateField() { - return repopulateField; - } - - public void setRepopulateField(boolean repopulateField) { - this.repopulateField = repopulateField; - } - - public void validate(Object object) throws ValidationException { - doValidate(object); - if (repopulateField) { - repopulateField(object); - } - } - - public void repopulateField(Object object) throws ValidationException { - - ActionInvocation invocation = ActionContext.getContext().getActionInvocation(); - Map conversionErrors = ActionContext.getContext().getConversionErrors(); - - String fieldName = getFieldName(); - String fullFieldName = getValidatorContext().getFullFieldName(fieldName); - if (conversionErrors.containsKey(fullFieldName)) { - Object value = conversionErrors.get(fullFieldName); - - final Map fakeParams = new LinkedHashMap(); - boolean doExprOverride = false; - - if (value instanceof String[]) { - // take the first element, if possible - String[] tmpValue = (String[]) value; - if ((tmpValue.length > 0)) { - doExprOverride = true; - fakeParams.put(fullFieldName, escape(tmpValue[0])); - } else { - LOG.warn("value is an empty array of String or with first element in it as null [{}], will not repopulate conversion error", value); - } - } else if (value instanceof String) { - String tmpValue = (String) value; - doExprOverride = true; - fakeParams.put(fullFieldName, escape(tmpValue)); - } else { - // opps... it should be - LOG.warn("conversion error value is not a String or array of String but instead is [{}], will not repopulate conversion error", value); - } - - if (doExprOverride) { - invocation.addPreResultListener(new PreResultListener() { - public void beforeResult(ActionInvocation invocation, String resultCode) { - ValueStack stack = ActionContext.getContext().getValueStack(); - stack.setExprOverrides(fakeParams); - } - }); - } - } - } - - protected String escape(String value) { - return "\"" + StringEscapeUtils.escapeJava(value) + "\""; - } - - protected abstract void doValidate(Object object) throws ValidationException; -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RequiredFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/RequiredFieldValidator.java deleted file mode 100644 index dffd37ac62..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RequiredFieldValidator.java +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.validator.ValidationException; - - -/** - * - * RequiredFieldValidator checks if the specified field is not null. - * - * - * - *
      - *
    • fieldName - field name if plain-validator syntax is used, not needed if field-validator syntax is used
    • - *
    - * - * - *
    - * 
    - * 	   <validators>
    - * 
    - *         <!-- Plain Validator Syntax -->
    - *         <validator type="required">
    - *             <param name="fieldName">username</param>
    - *             <message>username must not be null</message>
    - *         </validator>
    - * 
    - * 
    - *         <!-- Field Validator Syntax -->
    - *         <field name="username">
    - *             <field-validator type="required">
    - *             	   <message>username must not be null</message>
    - *             </field-validator>
    - *         </field>
    - * 
    - *     </validators>
    - * 
    - * 
    - * - * - * - * @author rainerh - */ -public class RequiredFieldValidator extends FieldValidatorSupport { - - public void validate(Object object) throws ValidationException { - String fieldName = getFieldName(); - Object value = this.getFieldValue(fieldName, object); - - if (value == null) { - addFieldError(fieldName, object); - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RequiredStringValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/RequiredStringValidator.java deleted file mode 100644 index af2d8072c8..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/RequiredStringValidator.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.validator.ValidationException; - - -/** - * - * RequiredStringValidator checks that a String field is non-null and has a length > 0. - * (i.e. it isn't ""). The "trim" parameter determines whether it will {@link String#trim() trim} - * the String before performing the length check. If unspecified, the String will be trimmed. - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    • trim - (Optional) Boolean, default true. Trims the field name value before validating.
    • - *
    • trimExpression - (Optional) String. Specifies the trim param as an OGNL expression.
    • - *
    - * - * - * - * Do not use ${trimExpression} as an expression as this will turn into infinitive loop! - * - * - *
    - * 
    - *     <validators>
    - *         <!-- Plain-Validator Syntax -->
    - *         <validator type="requiredstring">
    - *             <param name="fieldName">username</param>
    - *             <param name="trim">true</param>
    - *             <message>username is required</message>
    - *         </validator>
    - *         
    - *         <!-- Field-Validator Syntax -->
    - *         <field name="username">
    - *         	  <field-validator type="requiredstring">
    - *                 <param name="trim">true</param>
    - *                 <message>username is required</message>
    - *            </field-validator>
    - *         </field>
    - *
    - *         <!-- Field-Validator Syntax with expression -->
    - *         <field name="username">
    - *         	  <field-validator type="requiredstring">
    - *                 <param name="trimExpression">${trimValue}</param> <!-- will be evaluated as: boolean getTrimValue() -->
    - *                 <message>username is required</message>
    - *            </field-validator>
    - *         </field>
    - *     </validators>
    - * 
    - * 
    - * - * @author rainerh - */ -public class RequiredStringValidator extends FieldValidatorSupport { - - private boolean trim = true; - - public void setTrim(boolean trim) { - this.trim = trim; - } - - public void setTrimExpression(String trimExpression) { - trim = (Boolean) parse(trimExpression, Boolean.class); - } - - public boolean isTrim() { - return trim; - } - - public void validate(Object object) throws ValidationException { - String fieldName = getFieldName(); - Object value = this.getFieldValue(fieldName, object); - - if (!(value instanceof String)) { - addFieldError(fieldName, object); - } else { - String s = (String) value; - - if (trim) { - s = s.trim(); - } - - if (s.length() == 0) { - addFieldError(fieldName, object); - } - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/ShortRangeFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/ShortRangeFieldValidator.java deleted file mode 100644 index 8e5a9e6b28..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/ShortRangeFieldValidator.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -/** - * - * Field Validator that checks if the short specified is within a certain range. - * - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    • min - the minimum value (if none is specified, it will not be checked)
    • - *
    • max - the maximum value (if none is specified, it will not be checked)
    • - *
    • parse - if set to true, minExpression and maxExpression will be evaluated to find min/max
    • - *
    • minExpression - expression to calculate the minimum value (if none is specified, it will not be checked)
    • - *
    • maxExpression - expression to calculate the maximum value (if none is specified, it will not be checked)
    • - *
    - * - * You can either use the min / max value or minExpression / maxExpression (when parse is set to true) - - * using expression can be slightly slower, see the example below. - * - * - * - * Do not use ${minExpression} and ${maxExpression} as an expression as this will turn into infinitive loop! - * - * - *
    - * 
    - *  <validators>
    - *      <!-- Plain Validator Syntax -->
    - *      <validator type="short">
    - *          <param name="fieldName">age</param>
    - *          <param name="min">20</param>
    - *          <param name="max">50</param>
    - *          <message>Age needs to be between ${min} and ${max}</message>
    - *      </validator>
    - *
    - *      <!-- Field Validator Syntax -->
    - *      <field name="age">
    - *          <field-validator type="short">
    - *              <param name="min">20</param>
    - *              <param name="max">50</param>
    - *              <message>Age needs to be between ${min} and ${max}</message>
    - *          </field-validator>
    - *      </field>
    - *
    - *      <!-- Field Validator Syntax with expression -->
    - *      <field name="age">
    - *          <field-validator type="short">
    - *              <param name="minExpression">${minValue}</param> <!-- will be evaluated as: Short getMinValue() -->
    - *              <param name="maxExpression">${maxValue}</param> <!-- will be evaluated as: Short getMaxValue() -->
    - *              <message>Age needs to be between ${min} and ${max}</message>
    - *          </field-validator>
    - *      </field>
    - *  </validators>
    - * 
    - * 
    - * - * @version $Date$ - */ -public final class ShortRangeFieldValidator extends RangeValidatorSupport { - - public ShortRangeFieldValidator() { - super(Short.class); - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/StringLengthFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/StringLengthFieldValidator.java deleted file mode 100644 index 9d28a55ab2..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/StringLengthFieldValidator.java +++ /dev/null @@ -1,166 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.validator.ValidationException; -import org.apache.commons.lang3.StringUtils; - -/** - * - * StringLengthFieldValidator checks that a String field is of a certain length. If the "minLength" - * parameter is specified, it will make sure that the String has at least that many characters. If - * the "maxLength" parameter is specified, it will make sure that the String has at most that many - * characters. The "trim" parameter determines whether it will {@link String#trim() trim} the - * String before performing the length check. If unspecified, the String will be trimmed. - * - * - * - *
      - *
    • fieldName - The field name this validator is validating. Required if using Plain-Validator Syntax otherwise not required
    • - *
    • maxLength - Integer. The max length of the field value. Default ignore.
    • - *
    • minLength - Integer. The min length of the field value. Default ignore.
    • - *
    • trim - (Optional) Boolean, default true. Trim the field value before evaluating its min/max length. Default true.
    • - *
    • maxLengthExpression - (Optional) String. Defines the max length param as an OGNL expression
    • - *
    • minLengthExpression - (Optional) String. Defines the min length param as an OGNL expression
    • - *
    • trimExpression - (Optional) String. Defines th trim param as an OGNL expression
    • - *
    - * - * - * - * Do not use ${minLengthExpression}, ${maxLengthExpression} and ${trimExpression} as an expression as this will turn into infinitive loop! - * - * - *
    - * 
    - * <validators>
    - *     <!-- Plain Validator Syntax -->
    - *     <validator type="stringlength">
    - *         <param name="fieldName">myPurchaseCode</param>
    - *         <param name="minLength">10</param>
    - *         <param name="maxLength">10</param>
    - *         <param name="trim">true</param>
    - *         <message>Your purchase code needs to be 10 characters long</message>
    - *     </validator>
    - *
    - *     <!-- Field Validator Syntax -->
    - *     <field name="myPurchaseCode">
    - *         <field-validator type="stringlength">
    - *              <param name="minLength">10</param>
    - *              <param name="maxLength">10</param>
    - *              <param name="trim">true</param>
    - *              <message>Your purchase code needs to be 10 characters long</message>
    - *         </field-validator>
    - *     </field>
    - *
    - *     <!-- Field Validator Syntax with expression -->
    - *     <field name="myPurchaseCode">
    - *         <field-validator type="stringlength">
    - *              <param name="minLengthExpression">${minLengthValue}</param> <!-- will be evaluated as: Integer getMinLengthValue() -->
    - *              <param name="maxLengthExpression">${maxLengthValue}</param> <!-- will be evaluated as: Integer getMaxLengthValue() -->
    - *              <param name="trimExpression">${trimValue}</param> <!-- will be evaluated as: boolean getTrimValue() -->
    - *              <message>Your purchase code needs to be 10 characters long</message>
    - *         </field-validator>
    - *     </field>
    - * </validators>
    - * 
    - * 
    - * - * @author Jason Carreira - * @author Mark Woon - * @author tmjee - */ -public class StringLengthFieldValidator extends FieldValidatorSupport { - - private boolean trim = true; - private int maxLength = -1; - private int minLength = -1; - - private String maxLengthExpression; - private String minLengthExpression; - private String trimExpression; - - public void setMaxLength(int maxLength) { - this.maxLength = maxLength; - } - - public void setMaxLengthExpression(String maxLengthExpression) { - this.maxLengthExpression = maxLengthExpression; - } - - public int getMaxLength() { - if (StringUtils.isNotEmpty(maxLengthExpression)) { - return (Integer) parse(maxLengthExpression, Integer.class); - } - return maxLength; - } - - public void setMinLength(int minLength) { - this.minLength = minLength; - } - - public void setMinLengthExpression(String minLengthExpression) { - this.minLengthExpression = minLengthExpression; - } - - public int getMinLength() { - if (StringUtils.isNotEmpty(minLengthExpression)) { - return (Integer) parse(minLengthExpression, Integer.class); - } - return minLength; - } - - public void setTrim(boolean trim) { - this.trim = trim; - } - - public void setTrimExpression(String trimExpression) { - this.trimExpression = trimExpression; - } - - public boolean isTrim() { - if (StringUtils.isNotEmpty(trimExpression)) { - return (Boolean) parse(trimExpression, Boolean.class); - } - return trim; - } - - public void validate(Object object) throws ValidationException { - String fieldName = getFieldName(); - String val = (String) getFieldValue(fieldName, object); - - if (StringUtils.isEmpty(val)) { - // use a required validator for these - return; - } - if (isTrim()) { - val = val.trim(); - if (val.length() <= 0) { - // use a required validator - return; - } - } - - int minLengthToUse = getMinLength(); - int maxLengthToUse = getMaxLength(); - - if ((minLengthToUse > -1) && (val.length() < minLengthToUse)) { - addFieldError(fieldName, object); - } else if ((maxLengthToUse > -1) && (val.length() > maxLengthToUse)) { - addFieldError(fieldName, object); - } - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java deleted file mode 100644 index f12c28630b..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/URLValidator.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.validator.ValidationException; -import org.apache.commons.lang3.StringUtils; -import org.apache.logging.log4j.LogManager; -import org.apache.logging.log4j.Logger; - -import java.util.regex.Pattern; - -/** - * URLValidator checks that a given field is a String and a valid URL - * - *
    - * <validators>
    - *      <!-- Plain Validator Syntax -->
    - *      <validator type="url">
    - *          <param name="fieldName">myHomePage</param>
    - *          <message>Invalid homepage url</message>
    - *      </validator>
    - *
    - *      <!-- Field Validator Syntax -->
    - *      <field name="myHomepage">
    - *          <field-validator type="url">
    - *              <message>Invalid homepage url</message>
    - *          </field-validator>
    - *      </field>
    - * </validators>
    - * 
    - */ -public class URLValidator extends FieldValidatorSupport { - - private static final Logger LOG = LogManager.getLogger(URLValidator.class); - - public static final String DEFAULT_URL_REGEX = "^(https?|ftp):\\/\\/" + - "(([a-z0-9$_\\.\\+!\\*\\'\\(\\),;\\?&=-]|%[0-9a-f]{2})+" + - "(:([a-z0-9$_\\.\\+!\\*\\'\\(\\),;\\?&=-]|%[0-9a-f]{2})+)?" + - "@)?(#?" + - ")((([a-z0-9]\\.|[a-z0-9][a-z0-9-]*[a-z0-9]\\.)*" + - "[a-z][a-z0-9-]*[a-z0-9]" + - "|((\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])\\.){3}" + - "(\\d|[1-9]\\d|1\\d{2}|2[0-4][0-9]|25[0-5])" + - ")(:\\d+)?" + - ")(((\\/{0,1}([a-z0-9$_\\.\\+!\\*\\'\\(\\),;:@&=-]|%[0-9a-f]{2})*)*" + - "(\\?([a-z0-9$_\\.\\+!\\*\\'\\(\\),;:@&=-]|%[0-9a-f]{2})*)" + - "?)?)?" + - "(#([a-z0-9$_\\.\\+!\\*\\'\\(\\),;:@&=-]|%[0-9a-f]{2})*)?" + - "$"; - - private String urlRegexExpression; - private Pattern urlPattern = Pattern.compile(DEFAULT_URL_REGEX, Pattern.CASE_INSENSITIVE); - - public void validate(Object object) throws ValidationException { - String fieldName = getFieldName(); - Object value = this.getFieldValue(fieldName, object); - - // if there is no value - don't do comparison - // if a value is required, a required validator should be added to the field - if (value == null || value.toString().length() == 0) { - return; - } - - String stringValue = String.valueOf(value).trim(); - - if (!(value.getClass().equals(String.class)) || !getUrlPattern().matcher(stringValue).matches()) { - addFieldError(fieldName, object); - } - } - - protected Pattern getUrlPattern() { - if (StringUtils.isNotEmpty(urlRegexExpression)) { - String regex = (String) parse(urlRegexExpression, String.class); - if (regex == null) { - LOG.warn("Provided URL Regex expression [{}] was evaluated to null! Falling back to default!", urlRegexExpression); - urlPattern = Pattern.compile(DEFAULT_URL_REGEX, Pattern.CASE_INSENSITIVE); - } else { - urlPattern = Pattern.compile(regex, Pattern.CASE_INSENSITIVE); - } - } - return urlPattern; - } - - /** - * This is used to support client-side validation, it's based on - * http://stackoverflow.com/questions/161738/what-is-the-best-regular-expression-to-check-if-a-string-is-a-valid-url - * - * @return regex to validate URLs - */ - public String getUrlRegex() { - return getUrlPattern().pattern(); - } - - public void setUrlRegex(String urlRegex) { - urlPattern = Pattern.compile(urlRegex, Pattern.CASE_INSENSITIVE); - } - - public void setUrlRegexExpression(String urlRegexExpression) { - this.urlRegexExpression = urlRegexExpression; - } - -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java b/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java deleted file mode 100644 index 8fd62a63ae..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/VisitorFieldValidator.java +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. - */ -package com.opensymphony.xwork2.validator.validators; - -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.CompositeTextProvider; -import com.opensymphony.xwork2.TextProvider; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.validator.ActionValidatorManager; -import com.opensymphony.xwork2.validator.DelegatingValidatorContext; -import com.opensymphony.xwork2.validator.ValidationException; -import com.opensymphony.xwork2.validator.ValidatorContext; - -import java.util.Collection; -import java.util.LinkedList; -import java.util.List; - - -/** - * - * - *

    - * The VisitorFieldValidator allows you to forward validation to object - * properties of your action using the object's own validation files. This - * allows you to use the ModelDriven development pattern and manage your - * validations for your models in one place, where they belong, next to your - * model classes. The VisitorFieldValidator can handle either simple Object - * properties, Collections of Objects, or Arrays. - *

    - * - * - * - * - *
      - *
    • fieldName - field name if plain-validator syntax is used, not needed if field-validator syntax is used
    • - *
    • context - the context of which validation should take place. Optional
    • - *
    • appendPrefix - the prefix to be added to field. Optional
    • - *
    - * - * - *
    - * 
    - *    <validators>
    - *        <!-- Plain Validator Syntax -->
    - *        <validator type="visitor">
    - *            <param name="fieldName">user</param>
    - *            <param name="context">myContext</param>
    - *            <param name="appendPrefix">true</param>
    - *        </validator>
    - *
    - *        <!-- Field Validator Syntax -->
    - *        <field name="user">
    - *           <field-validator type="visitor">
    - *              <param name="context">myContext</param>
    - *              <param name="appendPrefix">true</param>
    - *           </field-validator>
    - *        </field>
    - *    </validators>
    - * 
    - * 
    - * - * - *

    In the example above, if the action's getUser() method return User object, XWork - * will look for User-myContext-validation.xml for the validators. Since appednPrefix is true, - * every field name will be prefixed with 'user' such that if the actual field name for 'name' is - * 'user.name'

    - * - * - * @author Jason Carreira - * @author Rainer Hermanns - */ -public class VisitorFieldValidator extends FieldValidatorSupport { - - private String context; - private boolean appendPrefix = true; - private ActionValidatorManager actionValidatorManager; - - - @Inject - public void setActionValidatorManager(ActionValidatorManager mgr) { - this.actionValidatorManager = mgr; - } - - /** - * @param appendPrefix whether the field name of this field validator should be prepended to the field name of - * the visited field to determine the full field name when an error occurs. The default is - * true. - */ - public void setAppendPrefix(boolean appendPrefix) { - this.appendPrefix = appendPrefix; - } - - /** - * @return whether the field name of this field validator should be prepended to the field name of - * the visited field to determine the full field name when an error occurs. The default is - * true. - */ - public boolean isAppendPrefix() { - return appendPrefix; - } - - public void setContext(String context) { - this.context = context; - } - - public String getContext() { - return context; - } - - public void validate(Object object) throws ValidationException { - String fieldName = getFieldName(); - Object value = this.getFieldValue(fieldName, object); - if (value == null) { - log.warn("The visited object is null, VisitorValidator will not be able to handle validation properly. Please make sure the visited object is not null for VisitorValidator to function properly"); - return; - } - ValueStack stack = ActionContext.getContext().getValueStack(); - - stack.push(object); - - String visitorContext = (context == null) ? ActionContext.getContext().getName() : context; - - if (value instanceof Collection) { - Collection coll = (Collection) value; - Object[] array = coll.toArray(); - - validateArrayElements(array, fieldName, visitorContext); - } else if (value instanceof Object[]) { - Object[] array = (Object[]) value; - - validateArrayElements(array, fieldName, visitorContext); - } else { - validateObject(fieldName, value, visitorContext); - } - - stack.pop(); - } - - private void validateArrayElements(Object[] array, String fieldName, String visitorContext) throws ValidationException { - if (array == null) { - return; - } - - for (int i = 0; i < array.length; i++) { - Object o = array[i]; - if (o != null) { - validateObject(fieldName + "[" + i + "]", o, visitorContext); - } - } - } - - private void validateObject(String fieldName, Object o, String visitorContext) throws ValidationException { - ValueStack stack = ActionContext.getContext().getValueStack(); - stack.push(o); - - ValidatorContext validatorContext; - - if (appendPrefix) { - ValidatorContext parent = getValidatorContext(); - validatorContext = new AppendingValidatorContext(parent, createTextProvider(o, parent), fieldName, getMessage(o)); - } else { - ValidatorContext parent = getValidatorContext(); - CompositeTextProvider textProvider = createTextProvider(o, parent); - validatorContext = new DelegatingValidatorContext(parent, textProvider, parent); - } - - actionValidatorManager.validate(o, visitorContext, validatorContext); - stack.pop(); - } - - private CompositeTextProvider createTextProvider(Object o, ValidatorContext parent) { - List textProviders = new LinkedList<>(); - if (o instanceof TextProvider) { - textProviders.add((TextProvider) o); - } else { - textProviders.add(textProviderFactory.createInstance(o.getClass())); - } - textProviders.add(parent); - - return new CompositeTextProvider(textProviders); - } - - public static class AppendingValidatorContext extends DelegatingValidatorContext { - private String field; - private String message; - private ValidatorContext parent; - - public AppendingValidatorContext(ValidatorContext parent, TextProvider textProvider, String field, String message) { - super(parent, textProvider, parent); - - this.field = field; - this.message = message; - this.parent = parent; - } - - /** - * Translates a simple field name into a full field name in Ognl syntax - * - * @param fieldName field name in OGNL syntax - * @return full field name in OGNL syntax - */ - @Override - public String getFullFieldName(String fieldName) { - if (parent instanceof VisitorFieldValidator.AppendingValidatorContext) { - return parent.getFullFieldName(field + "." + fieldName); - } - return field + "." + fieldName; - } - - public String getFieldNameWithField(String fieldName) { - return field + "." + fieldName; - } - - @Override - public void addActionError(String anErrorMessage) { - super.addFieldError(getFieldNameWithField(field), message + anErrorMessage); - } - - @Override - public void addFieldError(String fieldName, String errorMessage) { - super.addFieldError(getFieldNameWithField(fieldName), message + errorMessage); - } - } -} diff --git a/core/src/main/java/com/opensymphony/xwork2/validator/validators/package.html b/core/src/main/java/com/opensymphony/xwork2/validator/validators/package.html deleted file mode 100644 index 8b34399a2c..0000000000 --- a/core/src/main/java/com/opensymphony/xwork2/validator/validators/package.html +++ /dev/null @@ -1 +0,0 @@ -XWork default validator classes. diff --git a/core/src/main/java/org/apache/struts2/ActionContext.java b/core/src/main/java/org/apache/struts2/ActionContext.java new file mode 100644 index 0000000000..bad8f67057 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/ActionContext.java @@ -0,0 +1,559 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2; + +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.jsp.PageContext; +import org.apache.struts2.action.Action; +import org.apache.struts2.conversion.impl.ConversionData; +import org.apache.struts2.dispatcher.DispatcherConstants; +import org.apache.struts2.dispatcher.HttpParameters; +import org.apache.struts2.dispatcher.mapper.ActionMapping; +import org.apache.struts2.inject.Container; +import org.apache.struts2.util.ValueStack; + +import java.io.Serializable; +import java.util.HashMap; +import java.util.Locale; +import java.util.Map; +import java.util.Objects; + +/** + *

    + * The ActionContext is the context in which an {@link Action} is executed. Each context is basically a + * container of objects an action needs for execution like the session, parameters, locale, etc. + *

    + * + *

    + * The ActionContext is thread local which means that values stored in the ActionContext are + * unique per thread. See the {@link ThreadLocal} class for more information. The benefit of + * this is you don't need to worry about a user specific action context, you just get it: + *

    + * + * ActionContext context = ActionContext.getContext(); + * + *

    + * Finally, because of the thread local usage you don't need to worry about making your actions thread safe. + *

    + * + * @author Patrick Lightbody + * @author Bill Lynch (docs) + */ +public class ActionContext implements Serializable { + + private static final ThreadLocal actionContext = new ThreadLocal<>(); + + /** + * Constant for the name of the action being executed. + */ + private static final String ACTION_NAME = "org.apache.struts2.ActionContext.name"; + + /** + * Constant for the {@link org.apache.struts2.util.ValueStack OGNL value stack}. + */ + private static final String VALUE_STACK = ValueStack.VALUE_STACK; + + /** + * Constant for the action's session. + */ + private static final String SESSION = "org.apache.struts2.ActionContext.session"; + + /** + * Constant for the action's application context. + */ + private static final String APPLICATION = "org.apache.struts2.ActionContext.application"; + + /** + * Constant for the action's parameters. + */ + private static final String PARAMETERS = "org.apache.struts2.ActionContext.parameters"; + + /** + * Constant for the action's locale. + */ + private static final String LOCALE = "org.apache.struts2.ActionContext.locale"; + + /** + * Constant for the action's {@link ActionInvocation invocation} context. + */ + private static final String ACTION_INVOCATION = "org.apache.struts2.ActionContext.actionInvocation"; + + /** + * Constant for the map of type conversion errors. + */ + private static final String CONVERSION_ERRORS = "org.apache.struts2.ActionContext.conversionErrors"; + + /** + * Constant for the container + */ + private static final String CONTAINER = "org.apache.struts2.ActionContext.container"; + + private final Map context; + + /** + * Creates a new ActionContext initialized with another context. + * + * @param context a context map. + */ + protected ActionContext(Map context) { + this.context = context; + } + + /** + * Creates a new ActionContext based on passed in Map + * + * @param context a map with context values + * @return new ActionContext + */ + public static ActionContext of(Map context) { + if (context == null) { + throw new IllegalArgumentException("Context cannot be null!"); + } + return new ActionContext(context); + } + + /** + * Creates a new ActionContext based on empty Map + * + * @return new ActionContext + */ + public static ActionContext of() { + return of(new HashMap<>()); + } + + /** + * Binds the provided context with the current thread + * + * @param actionContext context to bind to the thread + * @return context which was bound to the thread + */ + public static ActionContext bind(ActionContext actionContext) { + ActionContext.setContext(actionContext); + return ActionContext.getContext(); + } + + public static boolean containsValueStack(Map context) { + return context != null && context.containsKey(VALUE_STACK); + } + + /** + * Binds this context with the current thread + * + * @return this context which was bound to the thread + */ + public ActionContext bind() { + ActionContext.setContext(this); + return ActionContext.getContext(); + } + + /** + * Wipes out current ActionContext, use wisely! + */ + public static void clear() { + actionContext.remove(); + } + + /** + * Sets the action context for the current thread. + * + * @param context the action context. + */ + private static void setContext(ActionContext context) { + actionContext.set(context); + } + + /** + * Returns the ActionContext specific to the current thread. + * + * @return the ActionContext for the current thread, is never null. + */ + public static ActionContext getContext() { + return actionContext.get(); + } + + /** + * Sets the action invocation (the execution state). + * + * @param actionInvocation the action execution state. + */ + public ActionContext withActionInvocation(ActionInvocation actionInvocation) { + put(ACTION_INVOCATION, actionInvocation); + return this; + } + + /** + * Gets the action invocation (the execution state). + * + * @return the action invocation (the execution state). + */ + public ActionInvocation getActionInvocation() { + return (ActionInvocation) get(ACTION_INVOCATION); + } + + /** + * Sets the action's application context. + * + * @param application the action's application context. + */ + public ActionContext withApplication(Map application) { + put(APPLICATION, application); + return this; + } + + /** + * Returns a Map of the ServletContext when in a servlet environment or a generic application level Map otherwise. + * + * @return a Map of ServletContext or generic application level Map + */ + @SuppressWarnings("unchecked") + public Map getApplication() { + return (Map) get(APPLICATION); + } + + /** + * Gets the context map. + * + * @return the context map. + */ + public Map getContextMap() { + return context; + } + + /** + * Sets conversion errors which occurred when executing the action. + * + * @param conversionErrors a Map of errors which occurred when executing the action. + */ + public ActionContext withConversionErrors(Map conversionErrors) { + put(CONVERSION_ERRORS, conversionErrors); + return this; + } + + /** + * Gets the map of conversion errors which occurred when executing the action. + * + * @return the map of conversion errors which occurred when executing the action or an empty map if + * there were no errors. + */ + @SuppressWarnings("unchecked") + public Map getConversionErrors() { + Map errors = (Map) get(CONVERSION_ERRORS); + + if (errors == null) { + errors = withConversionErrors(new HashMap<>()).getConversionErrors(); + } + + return errors; + } + + /** + * Sets the Locale for the current action. + * + * @param locale the Locale for the current action. + */ + public ActionContext withLocale(Locale locale) { + put(LOCALE, locale); + return this; + } + + /** + * Gets the Locale of the current action. If no locale was ever specified the platform's + * {@link java.util.Locale#getDefault() default locale} is used. + * + * @return the Locale of the current action. + */ + public Locale getLocale() { + Locale locale = (Locale) get(LOCALE); + + if (locale == null) { + locale = Locale.getDefault(); + withLocale(locale); + } + + return locale; + } + + /** + * Sets the name of the current Action in the ActionContext. + * + * @param actionName the name of the current action. + */ + public ActionContext withActionName(String actionName) { + put(ACTION_NAME, actionName); + return this; + } + + /** + * Gets the name of the current Action. + * + * @return the name of the current action. + */ + public String getActionName() { + return (String) get(ACTION_NAME); + } + + /** + * Sets the action parameters. + * + * @param parameters the parameters for the current action. + */ + public ActionContext withParameters(HttpParameters parameters) { + put(PARAMETERS, parameters); + put(DispatcherConstants.PARAMETERS, parameters); + return this; + } + + /** + * Returns a Map of the HttpServletRequest parameters when in a servlet environment or a generic Map of + * parameters otherwise. + * + * @return a Map of HttpServletRequest parameters or a multipart map when in a servlet environment, or a + * generic Map of parameters otherwise. + */ + public HttpParameters getParameters() { + return (HttpParameters) get(PARAMETERS); + } + + /** + * Sets a map of action session values. + * + * @param session the session values. + */ + public ActionContext withSession(Map session) { + put(SESSION, session); + return this; + } + + /** + * Gets the Map of HttpSession values when in a servlet environment or a generic session map otherwise. + * + * @return the Map of HttpSession values when in a servlet environment or a generic session map otherwise. + */ + @SuppressWarnings("unchecked") + public Map getSession() { + return (Map) get(SESSION); + } + + /** + * Sets the OGNL value stack. + * + * @param valueStack the OGNL value stack. + */ + public ActionContext withValueStack(ValueStack valueStack) { + put(VALUE_STACK, valueStack); + return this; + } + + /** + * Gets the OGNL value stack. + * + * @return the OGNL value stack. + */ + public ValueStack getValueStack() { + return (ValueStack) get(VALUE_STACK); + } + + /** + * Gets the container for this request + * + * @param container The container + */ + public ActionContext withContainer(Container container) { + put(CONTAINER, container); + return this; + } + + /** + * Sets the container for this request + * + * @return The container + */ + public Container getContainer() { + return (Container) get(CONTAINER); + } + + public T getInstance(Class type) { + Container cont = getContainer(); + if (cont != null) { + return cont.getInstance(type); + } else { + throw new StrutsException("Cannot find an initialized container for this request."); + } + } + + /** + * Returns a value that is stored in the current ActionContext by doing a lookup using the value's key. + * + * @param key the key used to find the value. + * @return the value that was found using the key or null if the key was not found. + */ + public Object get(String key) { + return context.get(key); + } + + /** + * Stores a value in the current ActionContext. The value can be looked up using the key. + * + * @param key the key of the value. + * @param value the value to be stored. + */ + public void put(String key, Object value) { + context.put(key, value); + } + + /** + * Gets ServletContext associated with current action + * + * @return current ServletContext + */ + public ServletContext getServletContext() { + return (ServletContext) get(StrutsStatics.SERVLET_CONTEXT); + } + + /** + * Assigns ServletContext to action context + * + * @param servletContext associated with current request + * @return ActionContext + */ + public ActionContext withServletContext(ServletContext servletContext) { + put(StrutsStatics.SERVLET_CONTEXT, servletContext); + return this; + } + + /** + * Gets ServletRequest associated with current action + * + * @return current ServletRequest + */ + public HttpServletRequest getServletRequest() { + return (HttpServletRequest) get(StrutsStatics.HTTP_REQUEST); + } + + /** + * Assigns ServletRequest to action context + * + * @param request associated with current request + * @return ActionContext + */ + public ActionContext withServletRequest(HttpServletRequest request) { + put(StrutsStatics.HTTP_REQUEST, request); + return this; + } + + /** + * Gets ServletResponse associated with current action + * + * @return current ServletResponse + */ + public HttpServletResponse getServletResponse() { + return (HttpServletResponse) get(StrutsStatics.HTTP_RESPONSE); + } + + /** + * Assigns ServletResponse to action context + * + * @param response associated with current request + * @return ActionContext + */ + public ActionContext withServletResponse(HttpServletResponse response) { + put(StrutsStatics.HTTP_RESPONSE, response); + return this; + } + + /** + * Gets PageContext associated with current action + * + * @return current PageContext + */ + public PageContext getPageContext() { + return (PageContext) get(StrutsStatics.PAGE_CONTEXT); + } + + /** + * Assigns PageContext to action context + * + * @param pageContext associated with current request + * @return ActionContext + */ + public ActionContext withPageContext(PageContext pageContext) { + put(StrutsStatics.PAGE_CONTEXT, pageContext); + return this; + } + + /** + * Gets ActionMapping associated with current action + * + * @return current ActionMapping + */ + public ActionMapping getActionMapping() { + return (ActionMapping) get(StrutsStatics.ACTION_MAPPING); + } + + /** + * Assigns ActionMapping to action context + * + * @param actionMapping associated with current request + * @return ActionContext + */ + public ActionContext withActionMapping(ActionMapping actionMapping) { + put(StrutsStatics.ACTION_MAPPING, actionMapping); + return this; + } + + /** + * Assigns an extra context map to action context + * + * @param extraContext to add to the current action context + * @return ActionContext + */ + public ActionContext withExtraContext(Map extraContext) { + if (extraContext != null) { + context.putAll(extraContext); + } + return this; + } + + /** + * Adds arbitrary key to action context + * + * @param key a string + * @param value an object + * @return ActionContext + */ + public ActionContext with(String key, Object value) { + put(key, value); + return this; + } + + @Override + public final boolean equals(Object obj) { + if (!(obj instanceof ActionContext other)) { + return false; + } + return Objects.equals(getContextMap(), other.getContextMap()); + } + + @Override + public final int hashCode() { + return Objects.hash(getContextMap()); + } +} diff --git a/core/src/main/java/org/apache/struts2/ActionEventListener.java b/core/src/main/java/org/apache/struts2/ActionEventListener.java new file mode 100644 index 0000000000..23077cc9ab --- /dev/null +++ b/core/src/main/java/org/apache/struts2/ActionEventListener.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.struts2; + +import org.apache.struts2.util.ValueStack; + +/** + * Provides hooks for handling key action events + */ +public interface ActionEventListener { + /** + * Called after an action has been created. + * + * @param action The action + * @param stack The current value stack + * @return The action to use + */ + Object prepare(Object action, ValueStack stack); + + /** + * Called when an exception is thrown by the action + * + * @param t The exception/error that was thrown + * @param stack The current value stack + * @return A result code to execute, can be null + */ + String handleException(Throwable t, ValueStack stack); +} diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionInvocation.java b/core/src/main/java/org/apache/struts2/ActionInvocation.java similarity index 77% rename from core/src/main/java/com/opensymphony/xwork2/ActionInvocation.java rename to core/src/main/java/org/apache/struts2/ActionInvocation.java index 1289c84483..bd52e185ae 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ActionInvocation.java +++ b/core/src/main/java/org/apache/struts2/ActionInvocation.java @@ -1,25 +1,28 @@ /* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.interceptor.PreResultListener; -import com.opensymphony.xwork2.util.ValueStack; - -import java.io.Serializable; +package org.apache.struts2; +import org.apache.struts2.action.Action; +import org.apache.struts2.interceptor.PreResultListener; +import org.apache.struts2.result.ActionChainResult; +import org.apache.struts2.result.Result; +import org.apache.struts2.util.ValueStack; /** * An {@link ActionInvocation} represents the execution state of an {@link Action}. It holds the Interceptors and the Action instance. @@ -27,9 +30,9 @@ * Interceptors are all executed, and then the {@link Action} and the {@link Result}. * * @author Jason Carreira - * @see com.opensymphony.xwork2.ActionProxy + * @see ActionProxy */ -public interface ActionInvocation extends Serializable { +public interface ActionInvocation { /** * Get the Action associated with this ActionInvocation. @@ -174,22 +177,6 @@ public interface ActionInvocation extends Serializable { */ void setActionEventListener(ActionEventListener listener); - void init(ActionProxy proxy) ; - - /** - * Prepares instance of ActionInvocation to be serializable, - * which simple means removing all unserializable fields, eg. Container - * - * @return ActionInvocation which can be serialize (eg. into HttpSession) - */ - ActionInvocation serialize(); - - /** - * Performs opposite process to restore back ActionInvocation after deserialisation - * - * @param actionContext current {@link ActionContext} - * @return fully operational ActionInvocation - */ - ActionInvocation deserialize(ActionContext actionContext); + void init(ActionProxy proxy); } diff --git a/core/src/main/java/org/apache/struts2/ActionProxy.java b/core/src/main/java/org/apache/struts2/ActionProxy.java new file mode 100644 index 0000000000..94b816bf8c --- /dev/null +++ b/core/src/main/java/org/apache/struts2/ActionProxy.java @@ -0,0 +1,102 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2; + +import org.apache.struts2.config.entities.ActionConfig; + +/** + * ActionProxy is an extra layer between XWork and the action so that different proxies are possible. + * + *

    + * An example of this would be a remote proxy, where the layer between XWork and the action might be RMI or SOAP. + *

    + * + * @author Jason Carreira + */ +public interface ActionProxy { + + /** + * Gets the Action instance for this Proxy. + * + * @return the Action instance + */ + Object getAction(); + + /** + * Gets the alias name this ActionProxy is mapped to. + * + * @return the alias name + */ + String getActionName(); + + /** + * Gets the ActionConfig this ActionProxy is built from. + * + * @return the ActionConfig + */ + ActionConfig getConfig(); + + /** + * Sets whether this ActionProxy should also execute the Result after executing the Action. + * + * @param executeResult true to also execute the Result. + */ + void setExecuteResult(boolean executeResult); + + /** + * Gets the status of whether the ActionProxy is set to execute the Result after the Action is executed. + * + * @return the status + */ + boolean getExecuteResult(); + + ActionInvocation getInvocation(); + + /** + * Gets the namespace the ActionConfig for this ActionProxy is mapped to. + * + * @return the namespace + */ + String getNamespace(); + + /** + * Execute this ActionProxy. This will set the ActionContext from the ActionInvocation into the ActionContext + * ThreadLocal before invoking the ActionInvocation, then set the old ActionContext back into the ThreadLocal. + * + * @return the result code returned from executing the ActionInvocation + * @throws Exception can be thrown. + * @see ActionInvocation + */ + String execute() throws Exception; + + /** + * Gets the method name to execute, or null if no method has been specified (meaning execute will be invoked). + * + * @return the method to execute + */ + String getMethod(); + + /** + * Gets status of the method value's initialization. + * + * @return true if the method returned by getMethod() is not a default initializer value. + */ + boolean isMethodSpecified(); + +} diff --git a/core/src/main/java/com/opensymphony/xwork2/ActionProxyFactory.java b/core/src/main/java/org/apache/struts2/ActionProxyFactory.java similarity index 80% rename from core/src/main/java/com/opensymphony/xwork2/ActionProxyFactory.java rename to core/src/main/java/org/apache/struts2/ActionProxyFactory.java index efbc1e6a0b..5cd4eab66e 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ActionProxyFactory.java +++ b/core/src/main/java/org/apache/struts2/ActionProxyFactory.java @@ -1,23 +1,25 @@ /* - * Copyright 2002-2007,2009 The Apache Software Foundation. - * - * 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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ -package com.opensymphony.xwork2; +package org.apache.struts2; import java.util.Map; - /** * The {@link ActionProxyFactory} is used to create {@link ActionProxy}s to be executed. * @@ -79,5 +81,5 @@ public interface ActionProxyFactory { */ ActionProxy createActionProxy(ActionInvocation actionInvocation, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext); - + } diff --git a/core/src/main/java/org/apache/struts2/ActionSupport.java b/core/src/main/java/org/apache/struts2/ActionSupport.java new file mode 100644 index 0000000000..578da01673 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/ActionSupport.java @@ -0,0 +1,367 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.struts2.action.Action; +import org.apache.struts2.conversion.impl.ConversionData; +import org.apache.struts2.inject.Container; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.interceptor.ValidationAware; +import org.apache.struts2.locale.LocaleProvider; +import org.apache.struts2.locale.LocaleProviderFactory; +import org.apache.struts2.text.TextProvider; +import org.apache.struts2.text.TextProviderFactory; +import org.apache.struts2.util.ValueStack; + +import java.io.Serializable; +import java.util.Collection; +import java.util.List; +import java.util.Locale; +import java.util.Map; +import java.util.ResourceBundle; + +/** + * Provides a default implementation for the most common actions. + * See the documentation for all the interfaces this class implements for more detailed information. + */ +public class ActionSupport implements Action, Validateable, ValidationAware, TextProvider, LocaleProvider, Serializable { + + private static final Logger LOG = LogManager.getLogger(ActionSupport.class); + + private final ValidationAwareSupport validationAware = new ValidationAwareSupport(); + + private transient TextProvider textProvider; + private transient LocaleProvider localeProvider; + + protected Container container; + + @Override + public void setActionErrors(Collection errorMessages) { + validationAware.setActionErrors(errorMessages); + } + + @Override + public Collection getActionErrors() { + return validationAware.getActionErrors(); + } + + @Override + public void setActionMessages(Collection messages) { + validationAware.setActionMessages(messages); + } + + @Override + public Collection getActionMessages() { + return validationAware.getActionMessages(); + } + + @Override + public void setFieldErrors(Map> errorMap) { + validationAware.setFieldErrors(errorMap); + } + + @Override + public Map> getFieldErrors() { + return validationAware.getFieldErrors(); + } + + @Override + public Locale getLocale() { + return getLocaleProvider().getLocale(); + } + + @Override + public boolean isValidLocaleString(String localeStr) { + return getLocaleProvider().isValidLocaleString(localeStr); + } + + @Override + public boolean isValidLocale(Locale locale) { + return getLocaleProvider().isValidLocale(locale); + } + + @Override + public Locale toLocale(String localeStr) { + return getLocaleProvider().toLocale(localeStr); + } + + @Override + public boolean hasKey(String key) { + return getTextProvider().hasKey(key); + } + + @Override + public String getText(String aTextName) { + return getTextProvider().getText(aTextName); + } + + @Override + public String getText(String aTextName, String defaultValue) { + return getTextProvider().getText(aTextName, defaultValue); + } + + @Override + public String getText(String aTextName, String defaultValue, String obj) { + return getTextProvider().getText(aTextName, defaultValue, obj); + } + + @Override + public String getText(String aTextName, List args) { + return getTextProvider().getText(aTextName, args); + } + + @Override + public String getText(String key, String[] args) { + return getTextProvider().getText(key, args); + } + + @Override + public String getText(String aTextName, String defaultValue, List args) { + return getTextProvider().getText(aTextName, defaultValue, args); + } + + @Override + public String getText(String key, String defaultValue, String[] args) { + return getTextProvider().getText(key, defaultValue, args); + } + + @Override + public String getText(String key, String defaultValue, List args, ValueStack stack) { + return getTextProvider().getText(key, defaultValue, args, stack); + } + + @Override + public String getText(String key, String defaultValue, String[] args, ValueStack stack) { + return getTextProvider().getText(key, defaultValue, args, stack); + } + + /** + * Dedicated method to support I10N and conversion errors + * + * @param key message which contains formatting string + * @param expr that should be formatted + * @return formatted expr with format specified by key + */ + public String getFormatted(String key, String expr) { + Map conversionErrors = ActionContext.getContext().getConversionErrors(); + if (conversionErrors.containsKey(expr)) { + String[] vals = (String[]) conversionErrors.get(expr).getValue(); + return vals[0]; + } else { + final ValueStack valueStack = ActionContext.getContext().getValueStack(); + final Object val = valueStack.findValue(expr); + return getText(key, List.of(val)); + } + } + + @Override + public ResourceBundle getTexts() { + return getTextProvider().getTexts(); + } + + @Override + public ResourceBundle getTexts(String aBundleName) { + return getTextProvider().getTexts(aBundleName); + } + + @Override + public void addActionError(String anErrorMessage) { + validationAware.addActionError(anErrorMessage); + } + + @Override + public void addActionMessage(String aMessage) { + validationAware.addActionMessage(aMessage); + } + + @Override + public void addFieldError(String fieldName, String errorMessage) { + validationAware.addFieldError(fieldName, errorMessage); + } + + public String input() throws Exception { + return INPUT; + } + + /** + * A default implementation that does nothing an returns "success". + * + *

    + * Subclasses should override this method to provide their business logic. + *

    + * + *

    + * See also {@link Action#execute()}. + *

    + * + * @return returns {@link #SUCCESS} + * @throws Exception can be thrown by subclasses. + */ + @Override + public String execute() throws Exception { + return SUCCESS; + } + + @Override + public boolean hasActionErrors() { + return validationAware.hasActionErrors(); + } + + @Override + public boolean hasActionMessages() { + return validationAware.hasActionMessages(); + } + + @Override + public boolean hasErrors() { + return validationAware.hasErrors(); + } + + @Override + public boolean hasFieldErrors() { + return validationAware.hasFieldErrors(); + } + + /** + * Clears field errors. Useful for Continuations and other situations + * where you might want to clear parts of the state on the same action. + */ + public void clearFieldErrors() { + validationAware.clearFieldErrors(); + } + + /** + * Clears action errors. Useful for Continuations and other situations + * where you might want to clear parts of the state on the same action. + */ + public void clearActionErrors() { + validationAware.clearActionErrors(); + } + + /** + * Clears messages. Useful for Continuations and other situations + * where you might want to clear parts of the state on the same action. + */ + public void clearMessages() { + validationAware.clearMessages(); + } + + /** + * Clears all errors. Useful for Continuations and other situations + * where you might want to clear parts of the state on the same action. + */ + public void clearErrors() { + validationAware.clearErrors(); + } + + /** + * Clears all errors and messages. Useful for Continuations and other situations + * where you might want to clear parts of the state on the same action. + */ + public void clearErrorsAndMessages() { + validationAware.clearErrorsAndMessages(); + } + + /** + * A default implementation that validates nothing. + * Subclasses should override this method to provide validations. + */ + @Override + public void validate() { + // A default implementation that validates nothing + } + + @Override + public Object clone() throws CloneNotSupportedException { + return super.clone(); + } + + /** + * + * Stops the action invocation immediately (by throwing a PauseException) and causes the action invocation to return + * the specified result, such as {@link #SUCCESS}, {@link #INPUT}, etc. + * + *

    + * The next time this action is invoked (and using the same continuation ID), the method will resume immediately + * after where this method was called, with the entire call stack in the execute method restored. + *

    + * + *

    + * Note: this method can only be called within the {@link #execute()} method. + *

    + * + * + * + * @param result the result to return - the same type of return value in the {@link #execute()} method. + */ + public void pause(String result) { + } + + /** + * If called first time it will create {@link TextProviderFactory}, + * inject dependency (if {@link Container} is accesible) into in, + * then will create new {@link TextProvider} and store it in a field + * for future references and at the returns reference to that field + * + * @return reference to field with TextProvider + */ + protected TextProvider getTextProvider() { + if (textProvider == null) { + final TextProviderFactory tpf = getContainer().getInstance(TextProviderFactory.class); + textProvider = tpf.createInstance(getClass()); + } + return textProvider; + } + + protected LocaleProvider getLocaleProvider() { + if (localeProvider == null) { + final LocaleProviderFactory localeProviderFactory = getContainer().getInstance(LocaleProviderFactory.class); + localeProvider = localeProviderFactory.createLocaleProvider(); + } + return localeProvider; + } + + /** + * TODO: This a temporary solution, maybe we should consider stop injecting container into beans + */ + protected Container getContainer() { + if (container == null) { + container = ActionContext.getContext().getContainer(); + if (container != null) { + boolean devMode = Boolean.parseBoolean(container.getInstance(String.class, StrutsConstants.STRUTS_DEVMODE)); + if (devMode) { + LOG.warn("Container is null, action was created manually? Fallback to ActionContext"); + } else { + LOG.debug("Container is null, action was created manually? Fallback to ActionContext"); + } + } else { + LOG.warn("Container is null, action was created out of ActionContext scope?!?"); + } + } + return container; + } + + @Inject + public void setContainer(Container container) { + this.container = container; + } + +} diff --git a/core/src/main/java/org/apache/struts2/AsyncManager.java b/core/src/main/java/org/apache/struts2/AsyncManager.java new file mode 100644 index 0000000000..aa433919a2 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/AsyncManager.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2; + +import java.util.concurrent.Callable; + +/** + * Adds support for invoke async actions. This allows us to support action methods that return {@link Callable} + * as well as invoking them in separate not-container thread then executing the result in another container thread. + * + * @since 6.0.0 + */ +public interface AsyncManager { + boolean hasAsyncActionResult(); + + Object getAsyncActionResult(); + + void invokeAsyncAction(Callable asyncAction); +} diff --git a/core/src/main/java/org/apache/struts2/DefaultActionInvocation.java b/core/src/main/java/org/apache/struts2/DefaultActionInvocation.java new file mode 100644 index 0000000000..cc477abc2d --- /dev/null +++ b/core/src/main/java/org/apache/struts2/DefaultActionInvocation.java @@ -0,0 +1,514 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2; + +import ognl.MethodFailedException; +import ognl.NoSuchPropertyException; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.apache.struts2.action.Action; +import org.apache.struts2.config.ConfigurationException; +import org.apache.struts2.config.entities.ActionConfig; +import org.apache.struts2.config.entities.InterceptorMapping; +import org.apache.struts2.config.entities.ResultConfig; +import org.apache.struts2.inject.Container; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.interceptor.ConditionalInterceptor; +import org.apache.struts2.interceptor.Interceptor; +import org.apache.struts2.interceptor.PreResultListener; +import org.apache.struts2.interceptor.WithLazyParams; +import org.apache.struts2.ognl.OgnlUtil; +import org.apache.struts2.result.ActionChainResult; +import org.apache.struts2.result.Result; +import org.apache.struts2.util.ValueStack; +import org.apache.struts2.util.ValueStackFactory; + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.concurrent.Callable; + +/** + * The Default ActionInvocation implementation + * + * @author Rainer Hermanns + * @author tmjee + * @version $Date$ $Id$ + * @see DefaultActionProxy + */ +public class DefaultActionInvocation implements ActionInvocation { + + private static final Logger LOG = LogManager.getLogger(DefaultActionInvocation.class); + + protected Object action; + protected ActionProxy proxy; + protected List preResultListeners; + protected Map extraContext; + protected ActionContext invocationContext; + protected Iterator interceptors; + protected ValueStack stack; + protected Result result; + protected Result explicitResult; + protected String resultCode; + protected boolean executed = false; + protected boolean pushAction; + protected ObjectFactory objectFactory; + protected ActionEventListener actionEventListener; + protected ValueStackFactory valueStackFactory; + protected Container container; + protected UnknownHandlerManager unknownHandlerManager; + protected OgnlUtil ognlUtil; + protected AsyncManager asyncManager; + protected Callable asyncAction; + protected WithLazyParams.LazyParamInjector lazyParamInjector; + + public DefaultActionInvocation(final Map extraContext, final boolean pushAction) { + this.extraContext = extraContext; + this.pushAction = pushAction; + } + + @Inject + public void setUnknownHandlerManager(UnknownHandlerManager unknownHandlerManager) { + this.unknownHandlerManager = unknownHandlerManager; + } + + @Inject + public void setValueStackFactory(ValueStackFactory fac) { + this.valueStackFactory = fac; + } + + @Inject + public void setObjectFactory(ObjectFactory fac) { + this.objectFactory = fac; + } + + @Inject + public void setContainer(Container cont) { + this.container = cont; + } + + @Inject(required = false) + @Override + public void setActionEventListener(ActionEventListener listener) { + this.actionEventListener = listener; + } + + @Inject + public void setOgnlUtil(OgnlUtil ognlUtil) { + this.ognlUtil = ognlUtil; + } + + @Inject(required = false) + public void setAsyncManager(AsyncManager asyncManager) { + this.asyncManager = asyncManager; + } + + @Override + public Object getAction() { + return action; + } + + @Override + public boolean isExecuted() { + return executed; + } + + @Override + public ActionContext getInvocationContext() { + return invocationContext; + } + + @Override + public ActionProxy getProxy() { + return proxy; + } + + /** + * If the DefaultActionInvocation has been executed before and the Result is an instance of ActionChainResult, this method + * will walk down the chain of ActionChainResults until it finds a non-chain result, which will be returned. If the + * DefaultActionInvocation's result has not been executed before, the Result instance will be created and populated with + * the result params. + * + * @return a Result instance + * @throws Exception in case of any error + */ + @Override + public Result getResult() throws Exception { + Result returnResult = result; + + // If we've chained to other Actions, we need to find the last result + while (returnResult instanceof ActionChainResult) { + ActionProxy aProxy = ((ActionChainResult) returnResult).getProxy(); + + if (aProxy != null) { + Result proxyResult = aProxy.getInvocation().getResult(); + + if ((proxyResult != null) && (aProxy.getExecuteResult())) { + returnResult = proxyResult; + } else { + break; + } + } else { + break; + } + } + + return returnResult; + } + + @Override + public String getResultCode() { + return resultCode; + } + + @Override + public void setResultCode(String resultCode) { + if (isExecuted()) { + throw new IllegalStateException("Result has already been executed."); + } + this.resultCode = resultCode; + } + + @Override + public ValueStack getStack() { + return stack; + } + + /** + * Register a org.apache.struts2.interceptor.PreResultListener to be notified after the Action is executed and before the + * Result is executed. The ActionInvocation implementation must guarantee that listeners will be called in the order + * in which they are registered. Listener registration and execution does not need to be thread-safe. + * + * @param listener to register + */ + @Override + public void addPreResultListener(PreResultListener listener) { + if (preResultListeners == null) { + preResultListeners = new ArrayList<>(1); + } + + preResultListeners.add(listener); + } + + public Result createResult() throws Exception { + LOG.trace("Creating result related to resultCode [{}]", resultCode); + + if (explicitResult != null) { + Result ret = explicitResult; + explicitResult = null; + + return ret; + } + ActionConfig config = proxy.getConfig(); + Map results = config.getResults(); + + ResultConfig resultConfig = null; + + try { + resultConfig = results.get(resultCode); + } catch (NullPointerException e) { + LOG.debug("Got NPE trying to read result configuration for resultCode [{}]", resultCode); + } + + if (resultConfig == null) { + // If no result is found for the given resultCode, try to get a wildcard '*' match. + resultConfig = results.get("*"); + } + + if (resultConfig != null) { + try { + return objectFactory.buildResult(resultConfig, invocationContext.getContextMap()); + } catch (Exception e) { + LOG.error("There was an exception while instantiating the result of type {}", resultConfig.getClassName(), e); + throw new StrutsException(e, resultConfig); + } + } else if (resultCode != null && !Action.NONE.equals(resultCode) && unknownHandlerManager.hasUnknownHandlers()) { + return unknownHandlerManager.handleUnknownResult(invocationContext, proxy.getActionName(), proxy.getConfig(), resultCode); + } + return null; + } + + /** + * @throws ConfigurationException If no result can be found with the returned code + */ + @Override + public String invoke() throws Exception { + if (executed) { + throw new IllegalStateException("Action has already executed"); + } + + if (asyncManager == null || !asyncManager.hasAsyncActionResult()) { + if (interceptors.hasNext()) { + final InterceptorMapping interceptorMapping = interceptors.next(); + Interceptor interceptor = interceptorMapping.getInterceptor(); + if (interceptor instanceof WithLazyParams) { + interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext); + } + if (interceptor instanceof ConditionalInterceptor conditionalInterceptor) { + resultCode = executeConditional(conditionalInterceptor); + } else { + LOG.debug("Executing normal interceptor: {}", interceptorMapping.getName()); + resultCode = interceptor.intercept(this); + } + } else { + resultCode = invokeActionOnly(); + } + } else { + Object asyncActionResult = asyncManager.getAsyncActionResult(); + if (asyncActionResult instanceof Throwable) { + throw new Exception((Throwable) asyncActionResult); + } + asyncAction = null; + resultCode = saveResult(proxy.getConfig(), asyncActionResult); + } + + if (asyncManager == null || asyncAction == null) { + // this is needed because the result will be executed, then control will return to the Interceptor, which will + // return above and flow through again + if (!executed) { + if (preResultListeners != null) { + LOG.trace("Executing PreResultListeners for result [{}]", result); + + for (PreResultListener listener : preResultListeners) { + listener.beforeResult(this, resultCode); + } + } + + // now execute the result, if we're supposed to + if (proxy.getExecuteResult()) { + executeResult(); + } + + executed = true; + } + } else { + asyncManager.invokeAsyncAction(asyncAction); + } + + return resultCode; + } + + protected String executeConditional(ConditionalInterceptor conditionalInterceptor) throws Exception { + if (conditionalInterceptor.shouldIntercept(this)) { + LOG.debug("Executing conditional interceptor: {}", conditionalInterceptor.getClass().getSimpleName()); + return conditionalInterceptor.intercept(this); + } else { + LOG.debug("Interceptor: {} is disabled, skipping to next", conditionalInterceptor.getClass().getSimpleName()); + return this.invoke(); + } + } + + @Override + public String invokeActionOnly() throws Exception { + return invokeAction(getAction(), proxy.getConfig()); + } + + protected void createAction(Map contextMap) { + // load action + try { + action = objectFactory.buildAction(proxy.getActionName(), proxy.getNamespace(), proxy.getConfig(), contextMap); + } catch (InstantiationException e) { + throw new StrutsException("Unable to instantiate Action!", e, proxy.getConfig()); + } catch (IllegalAccessException e) { + throw new StrutsException("Illegal access to constructor, is it public?", e, proxy.getConfig()); + } catch (Exception e) { + String gripe; + + if (proxy == null) { + gripe = "Whoa! No ActionProxy instance found in current ActionInvocation. This is bad ... very bad"; + } else if (proxy.getConfig() == null) { + gripe = "Sheesh. Where'd that ActionProxy get to? I can't find it in the current ActionInvocation!?"; + } else if (proxy.getConfig().getClassName() == null) { + gripe = "No Action defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'"; + } else { + gripe = "Unable to instantiate Action, " + proxy.getConfig().getClassName() + ", defined for '" + proxy.getActionName() + "' in namespace '" + proxy.getNamespace() + "'"; + } + + gripe += e.getMessage(); + throw new StrutsException(gripe, e, proxy.getConfig()); + } + + if (actionEventListener != null) { + action = actionEventListener.prepare(action, stack); + } + } + + protected Map createContextMap() { + ActionContext actionContext; + + if (ActionContext.containsValueStack(extraContext)) { + // In case the ValueStack was passed in + stack = ActionContext.of(extraContext).getValueStack(); + + if (stack == null) { + throw new IllegalStateException("There was a null Stack set into the extra params."); + } + + } else { + // create the value stack + // this also adds the ValueStack to its context + stack = valueStackFactory.createValueStack(); + + // create the action context + } + actionContext = stack.getActionContext(); + + return actionContext + .withExtraContext(extraContext) + .withActionInvocation(this) + .withContainer(container) + .getContextMap(); + } + + /** + * Uses getResult to get the final Result and executes it + * + * @throws ConfigurationException If not result can be found with the returned code + */ + private void executeResult() throws Exception { + result = createResult(); + + if (result != null) { + result.execute(this); + } else if (resultCode != null && !Action.NONE.equals(resultCode)) { + throw new ConfigurationException("No result defined for action " + getAction().getClass().getName() + + " and result " + getResultCode(), proxy.getConfig()); + } else { + if (LOG.isDebugEnabled()) { + LOG.debug("No result returned for action {} at {}", getAction().getClass().getName(), proxy.getConfig().getLocation()); + } + } + } + + @Override + public void init(ActionProxy proxy) { + this.proxy = proxy; + Map contextMap = createContextMap(); + + // Setting this so that other classes, like object factories, can use the ActionProxy and other + // contextual information to operate + ActionContext actionContext = ActionContext.getContext(); + + if (actionContext != null) { + actionContext.withActionInvocation(this); + } + + createAction(contextMap); + + if (pushAction) { + stack.push(action); + contextMap.put("action", action); + } + + invocationContext = ActionContext.of(contextMap) + .withActionName(proxy.getActionName()); + + createInterceptors(proxy); + + prepareLazyParamInjector(invocationContext.getValueStack()); + } + + protected void prepareLazyParamInjector(ValueStack valueStack) { + lazyParamInjector = new WithLazyParams.LazyParamInjector(valueStack); + container.inject(lazyParamInjector); + } + + protected void createInterceptors(ActionProxy proxy) { + // Get a new List so we don't get problems with the iterator if someone changes the original list + List interceptorList = new ArrayList<>(proxy.getConfig().getInterceptors()); + interceptors = interceptorList.iterator(); + } + + protected String invokeAction(Object action, ActionConfig actionConfig) throws Exception { + String methodName = proxy.getMethod(); + + LOG.debug("Executing action method = {}", methodName); + + try { + Object methodResult; + try { + methodResult = ognlUtil.callMethod(methodName + "()", getStack().getContext(), action); + } catch (MethodFailedException e) { + // if reason is missing method, try checking UnknownHandlers + if (e.getReason() instanceof NoSuchMethodException) { + if (unknownHandlerManager.hasUnknownHandlers()) { + try { + methodResult = unknownHandlerManager.handleUnknownMethod(action, methodName); + } catch (NoSuchMethodException ignore) { + // throw the original one + throw e; + } + } else { + // throw the original one + throw e; + } + // throw the original exception as UnknownHandlers weren't able to handle invocation as well + if (methodResult == null) { + throw e; + } + } else { + // exception isn't related to missing action method, throw it + throw e; + } + } + return saveResult(actionConfig, methodResult); + } catch (NoSuchPropertyException e) { + throw new IllegalArgumentException("The " + methodName + "() is not defined in action " + getAction().getClass()); + } catch (MethodFailedException e) { + // We try to return the source exception. + Throwable t = e.getCause(); + + if (actionEventListener != null) { + String result = actionEventListener.handleException(t, getStack()); + if (result != null) { + return result; + } + } + if (t instanceof Exception) { + throw (Exception) t; + } else { + throw e; + } + } + } + + /** + * Save the result to be used later. + * + * @param actionConfig current ActionConfig + * @param methodResult the result of the action. + * @return the result code to process. + */ + protected String saveResult(ActionConfig actionConfig, Object methodResult) { + if (methodResult instanceof Result) { + this.explicitResult = (Result) methodResult; + + // Wire the result automatically + container.inject(explicitResult); + return null; + } else if (methodResult instanceof Callable) { + asyncAction = (Callable) methodResult; + return null; + } else { + return (String) methodResult; + } + } + +} diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java b/core/src/main/java/org/apache/struts2/DefaultActionProxy.java similarity index 78% rename from core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java rename to core/src/main/java/org/apache/struts2/DefaultActionProxy.java index 87838bc89b..43fb695ec8 100644 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultActionProxy.java +++ b/core/src/main/java/org/apache/struts2/DefaultActionProxy.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,22 +16,22 @@ * specific language governing permissions and limitations * under the License. */ -package com.opensymphony.xwork2; - -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.profiling.UtilTimerStack; -import org.apache.commons.lang3.StringEscapeUtils; +package org.apache.struts2; + +import org.apache.struts2.config.Configuration; +import org.apache.struts2.config.ConfigurationException; +import org.apache.struts2.config.entities.ActionConfig; +import org.apache.struts2.inject.Inject; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.text.StringEscapeUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.struts2.text.LocalizedTextProvider; +import java.io.Serial; import java.io.Serializable; import java.util.Locale; - /** * The Default ActionProxy implementation * @@ -44,6 +42,7 @@ */ public class DefaultActionProxy implements ActionProxy, Serializable { + @Serial private static final long serialVersionUID = 3293074152487468527L; private static final Logger LOG = LogManager.getLogger(DefaultActionProxy.class); @@ -149,23 +148,15 @@ public String getNamespace() { public String execute() throws Exception { ActionContext nestedContext = ActionContext.getContext(); - ActionContext.setContext(invocation.getInvocationContext()); - - String retCode = null; + ActionContext.bind(invocation.getInvocationContext()); - String profileKey = "execute: "; try { - UtilTimerStack.push(profileKey); - - retCode = invocation.invoke(); + return invocation.invoke(); } finally { if (cleanupContext) { - ActionContext.setContext(nestedContext); + ActionContext.bind(nestedContext); } - UtilTimerStack.pop(profileKey); } - - return retCode; } @@ -186,27 +177,21 @@ private void resolveMethod() { } protected void prepare() { - String profileKey = "create DefaultActionProxy: "; - try { - UtilTimerStack.push(profileKey); - config = configuration.getRuntimeConfiguration().getActionConfig(namespace, actionName); + config = configuration.getRuntimeConfiguration().getActionConfig(namespace, actionName); - if (config == null && unknownHandlerManager.hasUnknownHandlers()) { - config = unknownHandlerManager.handleUnknownAction(namespace, actionName); - } - if (config == null) { - throw new ConfigurationException(getErrorMessage()); - } + if (config == null && unknownHandlerManager.hasUnknownHandlers()) { + config = unknownHandlerManager.handleUnknownAction(namespace, actionName); + } + if (config == null) { + throw new ConfigurationException(getErrorMessage()); + } - resolveMethod(); + resolveMethod(); - if (config.isAllowedMethod(method)) { - invocation.init(this); - } else { - throw new ConfigurationException(prepareNotAllowedErrorMessage()); - } - } finally { - UtilTimerStack.pop(profileKey); + if (config.isAllowedMethod(method)) { + invocation.init(this); + } else { + throw new ConfigurationException(prepareNotAllowedErrorMessage()); } } @@ -219,7 +204,7 @@ protected String prepareNotAllowedErrorMessage() { } protected String getErrorMessage() { - if ((namespace != null) && (namespace.trim().length() > 0)) { + if (namespace != null && !namespace.trim().isEmpty()) { return localizedTextProvider.findDefaultText( "xwork.exception.missing-package-action", Locale.getDefault(), diff --git a/core/src/main/java/org/apache/struts2/DefaultActionProxyFactory.java b/core/src/main/java/org/apache/struts2/DefaultActionProxyFactory.java new file mode 100644 index 0000000000..c74c5c0b89 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/DefaultActionProxyFactory.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.struts2; + +import org.apache.struts2.inject.Container; +import org.apache.struts2.inject.Inject; + +import java.util.Map; + +/** + * Default factory for {@link org.apache.struts2.ActionProxyFactory}. + * + * @author Jason Carreira + */ +public class DefaultActionProxyFactory implements ActionProxyFactory { + + protected Container container; + + public DefaultActionProxyFactory() { + super(); + } + + @Inject + public void setContainer(Container container) { + this.container = container; + } + + public ActionProxy createActionProxy(String namespace, String actionName, Map extraContext) { + return createActionProxy(namespace, actionName, null, extraContext, true, true); + } + + public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map extraContext) { + return createActionProxy(namespace, actionName, methodName, extraContext, true, true); + } + + public ActionProxy createActionProxy(String namespace, String actionName, Map extraContext, boolean executeResult, boolean cleanupContext) { + return createActionProxy(namespace, actionName, null, extraContext, executeResult, cleanupContext); + } + + @Override + public ActionProxy createActionProxy(String namespace, String actionName, String methodName, Map extraContext, boolean executeResult, boolean cleanupContext) { + + ActionInvocation inv = createActionInvocation(extraContext, true); + container.inject(inv); + return createActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); + } + + protected ActionInvocation createActionInvocation(Map extraContext, boolean pushAction) { + return new DefaultActionInvocation(extraContext, pushAction); + } + + public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, boolean executeResult, boolean cleanupContext) { + + return createActionProxy(inv, namespace, actionName, null, executeResult, cleanupContext); + } + + @Override + public ActionProxy createActionProxy(ActionInvocation inv, String namespace, String actionName, String methodName, boolean executeResult, boolean cleanupContext) { + + DefaultActionProxy proxy = new DefaultActionProxy(inv, namespace, actionName, methodName, executeResult, cleanupContext); + container.inject(proxy); + proxy.prepare(); + return proxy; + } + + @Override + public String toString() { + return getClass().getSimpleName(); + } + +} diff --git a/core/src/main/java/com/opensymphony/xwork2/DefaultUnknownHandlerManager.java b/core/src/main/java/org/apache/struts2/DefaultUnknownHandlerManager.java similarity index 78% rename from core/src/main/java/com/opensymphony/xwork2/DefaultUnknownHandlerManager.java rename to core/src/main/java/org/apache/struts2/DefaultUnknownHandlerManager.java index 46af876629..f7f92750e3 100644 --- a/core/src/main/java/com/opensymphony/xwork2/DefaultUnknownHandlerManager.java +++ b/core/src/main/java/org/apache/struts2/DefaultUnknownHandlerManager.java @@ -1,26 +1,30 @@ /* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ -package com.opensymphony.xwork2; +package org.apache.struts2; -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.config.entities.UnknownHandlerConfig; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; +import org.apache.struts2.config.Configuration; +import org.apache.struts2.config.ConfigurationException; +import org.apache.struts2.config.entities.ActionConfig; +import org.apache.struts2.config.entities.UnknownHandlerConfig; +import org.apache.struts2.inject.Container; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.result.Result; import java.util.ArrayList; import java.util.HashMap; @@ -30,7 +34,7 @@ /** * Default implementation of UnknownHandlerManager * - * @see com.opensymphony.xwork2.UnknownHandlerManager + * @see UnknownHandlerManager */ public class DefaultUnknownHandlerManager implements UnknownHandlerManager { @@ -65,7 +69,7 @@ protected void build() throws Exception { if (unkownHandlerStack != null && !unkownHandlerStack.isEmpty()) { //get UnknownHandlers in the specified order for (UnknownHandlerConfig unknownHandlerConfig : unkownHandlerStack) { - UnknownHandler uh = factory.buildUnknownHandler(unknownHandlerConfig.getName(), new HashMap()); + UnknownHandler uh = factory.buildUnknownHandler(unknownHandlerConfig.getName(), new HashMap<>()); unknownHandlers.add(uh); } } else { diff --git a/core/src/main/java/org/apache/struts2/FileManager.java b/core/src/main/java/org/apache/struts2/FileManager.java new file mode 100644 index 0000000000..f4d0d7cb1e --- /dev/null +++ b/core/src/main/java/org/apache/struts2/FileManager.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.struts2; + +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; +import java.util.Collection; + +/** + * Basic interface to access file on the File System and to monitor changes + */ +public interface FileManager { + + /** + * Enables configs reloading when config file changed + * + * @param reloadingConfigs {@link org.apache.struts2.StrutsConstants#STRUTS_CONFIGURATION_XML_RELOAD} + */ + void setReloadingConfigs(boolean reloadingConfigs); + + /** + * Checks if given file changed and must be reloaded + * + * @param fileName to check + * @return true if file changed + */ + boolean fileNeedsReloading(String fileName); + + /** + * Checks if file represented by provided URL changed and must be reloaded + * + * @param fileUrl url to a file + * @return true if file exists and should be reloaded, if url is null return false + */ + boolean fileNeedsReloading(URL fileUrl); + + /** + * Loads opens the named file and returns the InputStream + * + * @param fileUrl - the URL of the file to open + * @return an InputStream of the file contents or null + * @throws IllegalArgumentException if there is no file with the given file name + */ + InputStream loadFile(URL fileUrl); + + /** + * Adds file to list of monitored files + * + * @param fileUrl {@link URL} to file to be monitored + */ + void monitorFile(URL fileUrl); + + /** + * Convert URLs to URLs with "file" protocol + * @param url URL to convert to a jar url + * @return a URL to a file, or null if the URL external form cannot be parsed + */ + URL normalizeToFileProtocol(URL url); + + /** + * Indicate if given implementation supports current OS File System + * + * @return true if supports current OS File System + */ + boolean support(); + + /** + * User's implementation should return false as then it will be taken in first place + * + * @return true if it's a framework provided implementation + */ + boolean internal(); + + Collection getAllPhysicalUrls(URL url) throws IOException; + +} diff --git a/core/src/main/java/org/apache/struts2/FileManagerFactory.java b/core/src/main/java/org/apache/struts2/FileManagerFactory.java new file mode 100644 index 0000000000..7aacd73cce --- /dev/null +++ b/core/src/main/java/org/apache/struts2/FileManagerFactory.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.struts2; + +import org.apache.struts2.util.fs.DefaultFileManager; + +/** + * Factory that creates FileManager, default to {@link DefaultFileManager} + */ +public interface FileManagerFactory { + + void setReloadingConfigs(String reloadingConfigs); + + FileManager getFileManager(); + +} diff --git a/core/src/main/java/org/apache/struts2/ModelDriven.java b/core/src/main/java/org/apache/struts2/ModelDriven.java new file mode 100644 index 0000000000..dd21eb2f78 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/ModelDriven.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2; + +/** + * ModelDriven Actions provide a model object to be pushed onto the ValueStack + * in addition to the Action itself, allowing a FormBean type approach like Struts. + * + * @author Jason Carreira + */ +public interface ModelDriven { + + /** + * Gets the model to be pushed onto the ValueStack instead of the Action itself. + *

    + * Please be aware that all setters and getters of every depth on the object returned by this method are available + * for user parameter injection! + * + * @return the model + */ + T getModel(); + +} diff --git a/core/src/main/java/com/opensymphony/xwork2/ObjectFactory.java b/core/src/main/java/org/apache/struts2/ObjectFactory.java similarity index 77% rename from core/src/main/java/com/opensymphony/xwork2/ObjectFactory.java rename to core/src/main/java/org/apache/struts2/ObjectFactory.java index c5ffbb9d41..57838aa770 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ObjectFactory.java +++ b/core/src/main/java/org/apache/struts2/ObjectFactory.java @@ -1,44 +1,52 @@ /* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ -package com.opensymphony.xwork2; +package org.apache.struts2; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.config.entities.InterceptorConfig; -import com.opensymphony.xwork2.config.entities.ResultConfig; -import com.opensymphony.xwork2.conversion.TypeConverter; -import com.opensymphony.xwork2.factory.*; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.interceptor.Interceptor; -import com.opensymphony.xwork2.util.ClassLoaderUtil; -import com.opensymphony.xwork2.validator.Validator; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.struts2.config.ConfigurationException; +import org.apache.struts2.config.entities.ActionConfig; +import org.apache.struts2.config.entities.InterceptorConfig; +import org.apache.struts2.config.entities.ResultConfig; +import org.apache.struts2.conversion.TypeConverter; +import org.apache.struts2.factory.ActionFactory; +import org.apache.struts2.factory.ConverterFactory; +import org.apache.struts2.factory.InterceptorFactory; +import org.apache.struts2.factory.ResultFactory; +import org.apache.struts2.factory.UnknownHandlerFactory; +import org.apache.struts2.factory.ValidatorFactory; +import org.apache.struts2.inject.Container; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.interceptor.Interceptor; +import org.apache.struts2.result.Result; +import org.apache.struts2.util.ClassLoaderUtil; +import org.apache.struts2.validator.Validator; import java.io.Serializable; import java.util.Map; - /** - * ObjectFactory is responsible for building the core framework objects. Users may register their + * ObjectFactory is responsible for building the core framework objects. Users may register their * own implementation of the ObjectFactory to control instantiation of these Objects. * *

    - * This default implementation uses the {@link #buildBean(Class,java.util.Map) buildBean} + * This default implementation uses the {@link #buildBean(Class,java.util.Map) buildBean} * method to create all classes (interceptors, actions, results, etc). *

    * @@ -49,8 +57,8 @@ public class ObjectFactory implements Serializable { private static final Logger LOG = LogManager.getLogger(ObjectFactory.class); private transient ClassLoader ccl; - private Container container; + private Container container; private ActionFactory actionFactory; private ResultFactory resultFactory; private InterceptorFactory interceptorFactory; @@ -58,16 +66,19 @@ public class ObjectFactory implements Serializable { private ConverterFactory converterFactory; private UnknownHandlerFactory unknownHandlerFactory; - @Inject(value="objectFactory.classloader", required=false) - public void setClassLoader(ClassLoader cl) { - this.ccl = cl; + public ObjectFactory() { } - + @Inject public void setContainer(Container container) { this.container = container; } + @Inject(value=StrutsConstants.STRUTS_OBJECT_FACTORY_CLASSLOADER, required=false) + public void setClassLoader(ClassLoader cl) { + this.ccl = cl; + } + @Inject public void setActionFactory(ActionFactory actionFactory) { this.actionFactory = actionFactory; @@ -129,7 +140,7 @@ public Class getClassInstance(String className) throws ClassNotFoundException { * @param actionName the name the action configuration is set up with in the configuration * @param namespace the namespace the action is configured in * @param config the action configuration found in the config for the actionName / namespace - * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext} + * @param extraContext a Map of extra context which uses the same keys as the {@link org.apache.struts2.ActionContext} * @return instance of the action class to handle a web request * @throws Exception in case of any error */ @@ -141,12 +152,12 @@ public Object buildAction(String actionName, String namespace, ActionConfig conf * Build a generic Java object of the given type. * * @param clazz the type of Object to build - * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext} + * @param extraContext a Map of extra context which uses the same keys as the {@link org.apache.struts2.ActionContext} * @return object for the given type * @throws Exception in case of any error */ public Object buildBean(Class clazz, Map extraContext) throws Exception { - return clazz.newInstance(); + return container.inject(clazz); } /** @@ -155,6 +166,7 @@ public Object buildBean(Class clazz, Map extraContext) throws Ex */ protected Object injectInternalBeans(Object obj) { if (obj != null && container != null) { + LOG.debug("Injecting internal beans into [{}]", obj.getClass().getSimpleName()); container.inject(obj); } return obj; @@ -164,30 +176,26 @@ protected Object injectInternalBeans(Object obj) { * Build a generic Java object of the given type. * * @param className the type of Object to build - * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext} + * @param extraContext a Map of extra context which uses the same keys as the {@link org.apache.struts2.ActionContext} * @return object for the given type * @throws Exception in case of any error */ public Object buildBean(String className, Map extraContext) throws Exception { return buildBean(className, extraContext, true); } - + /** * Build a generic Java object of the given type. * * @param className the type of Object to build - * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext} + * @param extraContext a Map of extra context which uses the same keys as the {@link org.apache.struts2.ActionContext} * @param injectInternal true if inject internal beans * @return object for the given type * @throws Exception in case of any error */ public Object buildBean(String className, Map extraContext, boolean injectInternal) throws Exception { Class clazz = getClassInstance(className); - Object obj = buildBean(clazz, extraContext); - if (injectInternal) { - injectInternalBeans(obj); - } - return obj; + return buildBean(clazz, extraContext); } /** @@ -211,7 +219,7 @@ public Interceptor buildInterceptor(InterceptorConfig interceptorConfig, Map extraCo * * @param className the type of Validator to build * @param params property name -> value Map to set onto the Validator instance - * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext} + * @param extraContext a Map of extra context which uses the same keys as the {@link org.apache.struts2.ActionContext} * * @return validator of the given type * @throws Exception in case of any error @@ -238,7 +246,7 @@ public Validator buildValidator(String className, Map params, Ma * Build converter of given type * * @param converterClass to instantiate - * @param extraContext a Map of extra context which uses the same keys as the {@link com.opensymphony.xwork2.ActionContext} + * @param extraContext a Map of extra context which uses the same keys as the {@link org.apache.struts2.ActionContext} * @return instance of converterClass with inject dependencies * @throws Exception in case of any error */ @@ -257,5 +265,5 @@ public TypeConverter buildConverter(Class converterClas public UnknownHandler buildUnknownHandler(String unknownHandlerName, Map extraContext) throws Exception { return unknownHandlerFactory.buildUnknownHandler(unknownHandlerName, extraContext); } - + } diff --git a/core/src/main/java/org/apache/struts2/Preparable.java b/core/src/main/java/org/apache/struts2/Preparable.java new file mode 100644 index 0000000000..434c972c34 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/Preparable.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.struts2; + +/** + * Preparable Actions will have their prepare() method called if the + * {@link org.apache.struts2.interceptor.PrepareInterceptor} is applied to the ActionConfig. + * + * @author Jason Carreira + * @see org.apache.struts2.interceptor.PrepareInterceptor + */ +public interface Preparable { + + /** + * This method is called to allow the action to prepare itself. + * + * @throws Exception thrown if a system level exception occurs. + */ + void prepare() throws Exception; + +} diff --git a/core/src/main/java/org/apache/struts2/RequestUtils.java b/core/src/main/java/org/apache/struts2/RequestUtils.java index 393459a683..5840ff06b6 100644 --- a/core/src/main/java/org/apache/struts2/RequestUtils.java +++ b/core/src/main/java/org/apache/struts2/RequestUtils.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,21 +16,20 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.http.HttpServletRequest; import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.FastDateFormat; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import javax.servlet.http.HttpServletRequest; import java.text.ParseException; import java.util.Date; import java.util.Locale; import java.util.TimeZone; - /** * Request handling utility class. */ @@ -61,7 +58,7 @@ public class RequestUtils { */ public static String getServletPath(HttpServletRequest request) { String servletPath = request.getServletPath(); - + String requestUri = request.getRequestURI(); // Detecting other characters that the servlet container cut off (like anything after ';') if (requestUri != null && servletPath != null && !requestUri.endsWith(servletPath)) { @@ -74,8 +71,8 @@ public static String getServletPath(HttpServletRequest request) { if (StringUtils.isNotEmpty(servletPath)) { return servletPath; } - - int startIndex = request.getContextPath().equals("") ? 0 : request.getContextPath().length(); + + int startIndex = request.getContextPath().isEmpty() ? 0 : request.getContextPath().length(); int endIndex = request.getPathInfo() == null ? requestUri.length() : requestUri.lastIndexOf(request.getPathInfo()); if (startIndex > endIndex) { // this should not happen @@ -93,7 +90,7 @@ public static String getServletPath(HttpServletRequest request) { */ public static String getUri(HttpServletRequest request) { // handle http dispatcher includes. - String uri = (String) request.getAttribute("javax.servlet.include.servlet_path"); + String uri = (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); if (uri != null) { return uri; } diff --git a/core/src/main/java/org/apache/struts2/ServletActionContext.java b/core/src/main/java/org/apache/struts2/ServletActionContext.java index e3f50af5e0..9efccfce50 100644 --- a/core/src/main/java/org/apache/struts2/ServletActionContext.java +++ b/core/src/main/java/org/apache/struts2/ServletActionContext.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,35 +16,27 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.ActionContext; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.jsp.PageContext; import org.apache.struts2.dispatcher.mapper.ActionMapping; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.jsp.PageContext; -import java.util.Map; - - /** * Web-specific context information for actions. This class subclasses ActionContext which * provides access to things like the action name, value stack, etc. This class adds access to * web objects like servlet parameters, request attributes and things like the HTTP session. */ -public class ServletActionContext extends ActionContext implements StrutsStatics { - - private static final long serialVersionUID = -666854718275106687L; +public class ServletActionContext implements StrutsStatics { public static final String STRUTS_VALUESTACK_KEY = "struts.valueStack"; - public static final String ACTION_MAPPING = "struts.actionMapping"; @SuppressWarnings("unused") - private ServletActionContext(Map context) { - super(context); + private ServletActionContext() { } /** @@ -58,12 +48,15 @@ private ServletActionContext(Map context) { public static ActionContext getActionContext(HttpServletRequest req) { ValueStack vs = getValueStack(req); if (vs != null) { - return new ActionContext(vs.getContext()); + return ActionContext.of(vs.getContext()).bind(); } else { return null; } } + public static ActionContext getActionContext() { + return ActionContext.getContext(); + } /** * Gets the current value stack for this request * @@ -80,7 +73,7 @@ public static ValueStack getValueStack(HttpServletRequest req) { * @return The action mapping */ public static ActionMapping getActionMapping() { - return (ActionMapping) ActionContext.getContext().get(ACTION_MAPPING); + return ActionContext.getContext().getActionMapping(); } /** @@ -89,7 +82,7 @@ public static ActionMapping getActionMapping() { * @return the HTTP page context. */ public static PageContext getPageContext() { - return (PageContext) ActionContext.getContext().get(PAGE_CONTEXT); + return ActionContext.getContext().getPageContext(); } /** @@ -98,7 +91,7 @@ public static PageContext getPageContext() { * @param request the HTTP servlet request object. */ public static void setRequest(HttpServletRequest request) { - ActionContext.getContext().put(HTTP_REQUEST, request); + ActionContext.getContext().withServletRequest(request); } /** @@ -107,7 +100,7 @@ public static void setRequest(HttpServletRequest request) { * @return the HTTP servlet request object. */ public static HttpServletRequest getRequest() { - return (HttpServletRequest) ActionContext.getContext().get(HTTP_REQUEST); + return ActionContext.getContext().getServletRequest(); } /** @@ -116,7 +109,7 @@ public static HttpServletRequest getRequest() { * @param response the HTTP servlet response object. */ public static void setResponse(HttpServletResponse response) { - ActionContext.getContext().put(HTTP_RESPONSE, response); + ActionContext.getContext().withServletResponse(response); } /** @@ -125,7 +118,7 @@ public static void setResponse(HttpServletResponse response) { * @return the HTTP servlet response object. */ public static HttpServletResponse getResponse() { - return (HttpServletResponse) ActionContext.getContext().get(HTTP_RESPONSE); + return ActionContext.getContext().getServletResponse(); } /** @@ -134,7 +127,7 @@ public static HttpServletResponse getResponse() { * @return the servlet context. */ public static ServletContext getServletContext() { - return (ServletContext) ActionContext.getContext().get(SERVLET_CONTEXT); + return ActionContext.getContext().getServletContext(); } /** @@ -143,6 +136,6 @@ public static ServletContext getServletContext() { * @param servletContext The servlet context to use */ public static void setServletContext(ServletContext servletContext) { - ActionContext.getContext().put(SERVLET_CONTEXT, servletContext); + ActionContext.getContext().withServletContext(servletContext); } } diff --git a/core/src/main/java/org/apache/struts2/StrutsConstants.java b/core/src/main/java/org/apache/struts2/StrutsConstants.java index a868eddcf6..ae722ae4d2 100644 --- a/core/src/main/java/org/apache/struts2/StrutsConstants.java +++ b/core/src/main/java/org/apache/struts2/StrutsConstants.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2; -import org.apache.struts2.dispatcher.mapper.CompositeActionMapper; +import org.apache.struts2.components.date.DateFormatter; /** * This class provides a central location for framework configuration keys @@ -29,39 +26,77 @@ */ public final class StrutsConstants { - /** Whether Struts is in development mode or not */ + /** + * Whether Struts is in development mode or not + */ public static final String STRUTS_DEVMODE = "struts.devMode"; - /** Whether the localization messages should automatically be reloaded */ + /** + * Whether the localization messages should automatically be reloaded + */ public static final String STRUTS_I18N_RELOAD = "struts.i18n.reload"; - /** The encoding to use for localization messages */ + /** + * The encoding to use for localization messages + */ public static final String STRUTS_I18N_ENCODING = "struts.i18n.encoding"; - /** Whether to reload the XML configuration or not */ + /** + * Whether the default bundles should be searched for messages first. Can be used to modify the + * standard processing order for message lookup in TextProvider implementations. + *

    + * Note: This control flag may not be meaningful to all provider implementations, and should be false by default. + *

    + * + * @since 6.0.0 + */ + public static final String STRUTS_I18N_SEARCH_DEFAULTBUNDLES_FIRST = "struts.i18n.search.defaultbundles.first"; + + /** + * Whether to reload the XML configuration or not + */ public static final String STRUTS_CONFIGURATION_XML_RELOAD = "struts.configuration.xml.reload"; - /** The URL extension to use to determine if the request is meant for a Struts action */ + /** + * The URL extension to use to determine if the request is meant for a Struts action + */ public static final String STRUTS_ACTION_EXTENSION = "struts.action.extension"; - /** Comma separated list of patterns (java.util.regex.Pattern) to be excluded from Struts2-processing */ - public static final String STRUTS_ACTION_EXCLUDE_PATTERN = "struts.action.excludePattern"; + /** + * Comma separated list of patterns (java.util.regex.Pattern) to be excluded from Struts2-processing + */ + public static final String STRUTS_ACTION_EXCLUDE_PATTERN = "struts.action.excludePattern"; + + /** + * A custom separator used to split list of patterns (java.util.regex.Pattern) to be excluded from Struts2-processing + */ + public static final String STRUTS_ACTION_EXCLUDE_PATTERN_SEPARATOR = "struts.action.excludePattern.separator"; - /** Whether to use the alterative syntax for the tags or not */ - public static final String STRUTS_TAG_ALTSYNTAX = "struts.tag.altSyntax"; + /** + * Whether to use the response encoding (JSP page encoding) for s:include tag processing (false - use STRUTS_I18N_ENCODING - by default) + */ + public static final String STRUTS_TAG_INCLUDETAG_USERESPONSEENCODING = "struts.tag.includetag.useResponseEncoding"; - /** The HTTP port used by Struts URLs */ + /** + * The HTTP port used by Struts URLs + */ public static final String STRUTS_URL_HTTP_PORT = "struts.url.http.port"; - /** The HTTPS port used by Struts URLs */ + /** + * The HTTPS port used by Struts URLs + */ public static final String STRUTS_URL_HTTPS_PORT = "struts.url.https.port"; - /** The default includeParams method to generate Struts URLs */ + /** + * The default includeParams method to generate Struts URLs + */ public static final String STRUTS_URL_INCLUDEPARAMS = "struts.url.includeParams"; - public static final String STRUTS_URL_RENDERER = "struts.urlRenderer"; + public static final String STRUTS_URL_RENDERER = "struts.urlRenderer"; - /** The com.opensymphony.xwork2.ObjectFactory implementation class */ + /** + * The org.apache.struts2.ObjectFactory implementation class + */ public static final String STRUTS_OBJECTFACTORY = "struts.objectFactory"; public static final String STRUTS_OBJECTFACTORY_ACTIONFACTORY = "struts.objectFactory.actionFactory"; public static final String STRUTS_OBJECTFACTORY_RESULTFACTORY = "struts.objectFactory.resultFactory"; @@ -70,68 +105,137 @@ public final class StrutsConstants { public static final String STRUTS_OBJECTFACTORY_VALIDATORFACTORY = "struts.objectFactory.validatorFactory"; public static final String STRUTS_OBJECTFACTORY_UNKNOWNHANDLERFACTORY = "struts.objectFactory.unknownHandlerFactory"; - /** The com.opensymphony.xwork2.util.FileManager implementation class */ + /** + * The org.apache.struts2.util.FileManager implementation class + */ public static final String STRUTS_FILE_MANAGER_FACTORY = "struts.fileManagerFactory"; - /** The com.opensymphony.xwork2.util.fs.FileManager implementation class */ + /** + * The org.apache.struts2.util.fs.FileManager implementation class + */ public static final String STRUTS_FILE_MANAGER = "struts.fileManager"; - /** The com.opensymphony.xwork2.util.ObjectTypeDeterminer implementation class */ + /** + * The org.apache.struts2.util.ObjectTypeDeterminer implementation class + */ public static final String STRUTS_OBJECTTYPEDETERMINER = "struts.objectTypeDeterminer"; - /** The package containing actions that use Rife continuations */ + /** + * The package containing actions that use Rife continuations + */ public static final String STRUTS_CONTINUATIONS_PACKAGE = "struts.continuations.package"; - /** The org.apache.struts2.config.Configuration implementation class */ + /** + * The org.apache.struts2.config.Configuration implementation class + */ public static final String STRUTS_CONFIGURATION = "struts.configuration"; - /** The default locale for the Struts application */ + /** + * The default locale for the Struts application + */ public static final String STRUTS_LOCALE = "struts.locale"; - /** Whether to use a Servlet request parameter workaround necessary for some versions of WebLogic */ + /** + * Whether to use a Servlet request parameter workaround necessary for some versions of WebLogic + */ public static final String STRUTS_DISPATCHER_PARAMETERSWORKAROUND = "struts.dispatcher.parametersWorkaround"; - /** The org.apache.struts2.views.freemarker.FreemarkerManager implementation class */ + /** + * The org.apache.struts2.views.freemarker.FreemarkerManager implementation class + */ public static final String STRUTS_FREEMARKER_MANAGER_CLASSNAME = "struts.freemarker.manager.classname"; - /** Update freemarker templates cache in seconds*/ + /** + * Update freemarker templates cache in seconds + */ public static final String STRUTS_FREEMARKER_TEMPLATES_CACHE_UPDATE_DELAY = "struts.freemarker.templatesCache.updateDelay"; - - /** Cache model instances at BeanWrapper level */ + + /** + * Cache model instances at BeanWrapper level + */ public static final String STRUTS_FREEMARKER_BEANWRAPPER_CACHE = "struts.freemarker.beanwrapperCache"; - - /** Maximum strong sizing for MruCacheStorage for freemarker */ + + /** + * Maximum strong sizing for MruCacheStorage for freemarker + */ public static final String STRUTS_FREEMARKER_MRU_MAX_STRONG_SIZE = "struts.freemarker.mru.max.strong.size"; - - /** org.apache.struts2.views.velocity.VelocityManager implementation class */ - public static final String STRUTS_VELOCITY_MANAGER_CLASSNAME = "struts.velocity.manager.classname"; - /** The Velocity configuration file path */ + /** + * The Velocity configuration file path + */ public static final String STRUTS_VELOCITY_CONFIGFILE = "struts.velocity.configfile"; - /** The location of the Velocity toolbox */ + /** + * The location of the Velocity toolbox + */ public static final String STRUTS_VELOCITY_TOOLBOXLOCATION = "struts.velocity.toolboxlocation"; - /** List of Velocity context names */ + /** + * List of Velocity context names + */ public static final String STRUTS_VELOCITY_CONTEXTS = "struts.velocity.contexts"; - /** The directory containing UI templates. All templates must reside in this directory. */ + /** + * The directory containing UI templates. All templates must reside in this directory. + */ public static final String STRUTS_UI_TEMPLATEDIR = "struts.ui.templateDir"; - /** The default UI template theme */ + /** + * The default UI template theme + */ public static final String STRUTS_UI_THEME = "struts.ui.theme"; - /** Token to use to indicate start of theme to be expanded. */ + /** + * Token to use to indicate start of theme to be expanded. + */ public static final String STRUTS_UI_THEME_EXPANSION_TOKEN = "struts.ui.theme.expansion.token"; - /** The maximize size of a multipart request (file upload) */ - public static final String STRUTS_MULTIPART_MAXSIZE = "struts.multipart.maxSize"; + /** + * A path to static content, by default and from historical point of view it's /static. + */ + public static final String STRUTS_UI_STATIC_CONTENT_PATH = "struts.ui.staticContentPath"; + + /** + * A global flag to enable/disable html body escaping in tags, can be overwritten per tag + */ + public static final String STRUTS_UI_ESCAPE_HTML_BODY = "struts.ui.escapeHtmlBody"; + + /** + * The maximum size of a multipart request (file upload) + */ + public static final String STRUTS_MULTIPART_MAX_SIZE = "struts.multipart.maxSize"; + + /** + * The maximum size of all uploaded files. + * Used only with {@link org.apache.struts2.dispatcher.multipart.JakartaStreamMultiPartRequest} + */ + public static final String STRUTS_MULTIPART_MAX_SIZE_OF_FILES = "struts.multipart.maxSizeOfFiles"; + + /** + * The maximum number of files allowed in a multipart request + */ + public static final String STRUTS_MULTIPART_MAX_FILES = "struts.multipart.maxFiles"; + + /** + * The maximum length of a string parameter in a multipart request. + */ + public static final String STRUTS_MULTIPART_MAX_STRING_LENGTH = "struts.multipart.maxStringLength"; + + /** + * The maximum size per file in a multipart request + */ + public static final String STRUTS_MULTIPART_MAX_FILE_SIZE = "struts.multipart.maxFileSize"; - /** The directory to use for storing uploaded files */ - public static final String STRUTS_MULTIPART_SAVEDIR = "struts.multipart.saveDir"; + /** + * The directory to use for storing uploaded files + */ + public static final String STRUTS_MULTIPART_SAVE_DIR = "struts.multipart.saveDir"; - /** Declares the buffer size to be used during streaming multipart content to disk. Used only with {@link org.apache.struts2.dispatcher.multipart.JakartaStreamMultiPartRequest} */ - public static final String STRUTS_MULTIPART_BUFFERSIZE = "struts.multipart.bufferSize"; + /** + * Declares the buffer size to be used during streaming multipart content to disk. + * Used only with {@link org.apache.struts2.dispatcher.multipart.JakartaStreamMultiPartRequest} + */ + public static final String STRUTS_MULTIPART_BUFFER_SIZE = "struts.multipart.bufferSize"; /** * The org.apache.struts2.dispatcher.multipart.MultiPartRequest parser implementation @@ -139,31 +243,50 @@ public final class StrutsConstants { */ public static final String STRUTS_MULTIPART_PARSER = "struts.multipart.parser"; - /** How Spring should autowire. Valid values are 'name', 'type', 'auto', and 'constructor' */ + /** + * A global switch to disable support for multipart requests + */ + public static final String STRUTS_MULTIPART_ENABLED = "struts.multipart.enabled"; + + public static final String STRUTS_MULTIPART_VALIDATION_REGEX = "struts.multipart.validationRegex"; + + /** + * How Spring should autowire. Valid values are 'name', 'type', 'auto', and 'constructor' + */ public static final String STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE = "struts.objectFactory.spring.autoWire"; - /** Whether the autowire strategy chosen by STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE is always respected. Defaults + /** + * Whether the autowire strategy chosen by STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE is always respected. Defaults * to false, which is the legacy behavior that tries to determine the best strategy for the situation. + * * @since 2.1.3 */ public static final String STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE_ALWAYS_RESPECT = "struts.objectFactory.spring.autoWire.alwaysRespect"; - /** Whether Spring should use its class cache or not */ + /** + * Whether Spring should use its class cache or not + */ public static final String STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE = "struts.objectFactory.spring.useClassCache"; - /** Uses different logic to construct beans, see https://issues.apache.org/jira/browse/WW-4110 */ + /** + * Uses different logic to construct beans, see https://issues.apache.org/jira/browse/WW-4110 + */ + @Deprecated public static final String STRUTS_OBJECTFACTORY_SPRING_ENABLE_AOP_SUPPORT = "struts.objectFactory.spring.enableAopSupport"; - /** Whether or not XSLT templates should not be cached */ - public static final String STRUTS_XSLT_NOCACHE = "struts.xslt.nocache"; - - /** Location of additional configuration properties files to load */ + /** + * Location of additional configuration properties files to load + */ public static final String STRUTS_CUSTOM_PROPERTIES = "struts.custom.properties"; - /** Location of additional localization properties files to load */ + /** + * Location of additional localization properties files to load + */ public static final String STRUTS_CUSTOM_I18N_RESOURCES = "struts.custom.i18n.resources"; - /** The org.apache.struts2.dispatcher.mapper.ActionMapper implementation class */ + /** + * A name of a bean implementing org.apache.struts2.dispatcher.mapper.ActionMapper interface + */ public static final String STRUTS_MAPPER_CLASS = "struts.mapper.class"; /** @@ -172,149 +295,382 @@ public final class StrutsConstants { * You can specify different prefixes that will be handled by different mappers */ public static final String PREFIX_BASED_MAPPER_CONFIGURATION = "struts.mapper.prefixMapping"; - - /** Whether the Struts filter should serve static content or not */ + + /** + * Whether the Struts filter should serve static content or not + */ public static final String STRUTS_SERVE_STATIC_CONTENT = "struts.serve.static"; - /** If static content served by the Struts filter should set browser caching header properties or not */ + /** + * If static content served by the Struts filter should set browser caching header properties or not + */ public static final String STRUTS_SERVE_STATIC_BROWSER_CACHE = "struts.serve.static.browserCache"; - /** Allows one to disable dynamic method invocation from the URL */ + /** + * Allows one to disable dynamic method invocation from the URL + */ public static final String STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION = "struts.enable.DynamicMethodInvocation"; - /** Whether slashes in action names are allowed or not */ + /** + * Whether slashes in action names are allowed or not + */ public static final String STRUTS_ENABLE_SLASHES_IN_ACTION_NAMES = "struts.enable.SlashesInActionNames"; - /** Prefix used by {@link CompositeActionMapper} to identify its containing {@link org.apache.struts2.dispatcher.mapper.ActionMapper} class. */ + /** + * Prefix used by {@link org.apache.struts2.dispatcher.mapper.CompositeActionMapper} to identify + * its containing {@link org.apache.struts2.dispatcher.mapper.ActionMapper} class. + */ public static final String STRUTS_MAPPER_COMPOSITE = "struts.mapper.composite"; public static final String STRUTS_ACTIONPROXYFACTORY = "struts.actionProxyFactory"; public static final String STRUTS_FREEMARKER_WRAPPER_ALT_MAP = "struts.freemarker.wrapper.altMap"; - /** The name of the xwork converter implementation */ + /** + * Extension point for the Struts CompoundRootAccessor + */ + public static final String STRUTS_COMPOUND_ROOT_ACCESSOR = "struts.compoundRootAccessor"; + + /** + * Extension point for the Struts MethodAccessor + */ + public static final String STRUTS_METHOD_ACCESSOR = "struts.methodAccessor"; + + /** + * The name of the xwork converter implementation + */ public static final String STRUTS_XWORKCONVERTER = "struts.xworkConverter"; public static final String STRUTS_ALWAYS_SELECT_FULL_NAMESPACE = "struts.mapper.alwaysSelectFullNamespace"; + /** + * Fallback to empty namespace when request namespace didn't match any in action configuration + */ + public static final String STRUTS_ACTION_CONFIG_FALLBACK_TO_EMPTY_NAMESPACE = "struts.actionConfig.fallbackToEmptyNamespace"; - /** XWork default text provider */ - public static final String STRUTS_XWORKTEXTPROVIDER = "struts.xworkTextProvider"; + /** + * The {@link org.apache.struts2.locale.LocaleProviderFactory} implementation class + */ + public static final String STRUTS_LOCALE_PROVIDER_FACTORY = "struts.localeProviderFactory"; /** - * The {@link com.opensymphony.xwork2.LocaleProvider} implementation class - * @deprecated use {@link StrutsConstants#STRUTS_LOCALE_PROVIDER_FACTORY} instead + * The name of the parameter to create when mapping an id (used by some action mappers) */ - @Deprecated - public static final String STRUTS_LOCALE_PROVIDER = "struts.localeProvider"; + public static final String STRUTS_ID_PARAMETER_NAME = "struts.mapper.idParameterName"; - /** The {@link com.opensymphony.xwork2.LocaleProviderFactory} implementation class */ - public static final String STRUTS_LOCALE_PROVIDER_FACTORY = "struts.localeProviderFactory"; + /** + * The name of the parameter to determine whether static field access will be allowed in OGNL expressions or not + */ + public static final String STRUTS_ALLOW_STATIC_FIELD_ACCESS = "struts.ognl.allowStaticFieldAccess"; + + public static final String STRUTS_DISALLOW_CUSTOM_OGNL_MAP = "struts.ognl.disallowCustomOgnlMap"; - /** The name of the parameter to create when mapping an id (used by some action mappers) */ - public static final String STRUTS_ID_PARAMETER_NAME = "struts.mapper.idParameterName"; - - /** The name of the parameter to determine whether static method access will be allowed in OGNL expressions or not */ - public static final String STRUTS_ALLOW_STATIC_METHOD_ACCESS = "struts.ognl.allowStaticMethodAccess"; + public static final String STRUTS_MEMBER_ACCESS = "struts.securityMemberAccess"; - /** The com.opensymphony.xwork2.validator.ActionValidatorManager implementation class */ + public static final String STRUTS_OGNL_GUARD = "struts.ognlGuard"; + + /** + * The org.apache.struts2.validator.ActionValidatorManager implementation class + */ public static final String STRUTS_ACTIONVALIDATORMANAGER = "struts.actionValidatorManager"; - /** The {@link com.opensymphony.xwork2.util.ValueStackFactory} implementation class */ + /** + * The {@link org.apache.struts2.util.ValueStackFactory} implementation class + */ public static final String STRUTS_VALUESTACKFACTORY = "struts.valueStackFactory"; - /** The {@link com.opensymphony.xwork2.util.reflection.ReflectionProvider} implementation class */ + /** + * The {@link org.apache.struts2.util.reflection.ReflectionProvider} implementation class + */ public static final String STRUTS_REFLECTIONPROVIDER = "struts.reflectionProvider"; - /** The {@link com.opensymphony.xwork2.util.reflection.ReflectionContextFactory} implementation class */ + /** + * The {@link org.apache.struts2.util.reflection.ReflectionContextFactory} implementation class + */ public static final String STRUTS_REFLECTIONCONTEXTFACTORY = "struts.reflectionContextFactory"; - - /** The {@link com.opensymphony.xwork2.util.PatternMatcher} implementation class */ + + /** + * The {@link org.apache.struts2.util.PatternMatcher} implementation class + */ public static final String STRUTS_PATTERNMATCHER = "struts.patternMatcher"; - /** The {@link org.apache.struts2.dispatcher.StaticContentLoader} implementation class */ + /** + * The {@link org.apache.struts2.dispatcher.StaticContentLoader} implementation class + */ public static final String STRUTS_STATIC_CONTENT_LOADER = "struts.staticContentLoader"; - /** The {@link com.opensymphony.xwork2.UnknownHandlerManager} implementation class */ + /** + * The {@link org.apache.struts2.UnknownHandlerManager} implementation class + */ public static final String STRUTS_UNKNOWN_HANDLER_MANAGER = "struts.unknownHandlerManager"; - /** Throw RuntimeException when a property is not found, or the evaluation of the espression fails*/ + /** + * Throw RuntimeException when a property is not found, or the evaluation of the expression fails + */ public static final String STRUTS_EL_THROW_EXCEPTION = "struts.el.throwExceptionOnFailure"; - /** Logs properties that are not found (very verbose) **/ - public static final String STRUTS_LOG_MISSING_PROPERTIES = "struts.ognl.logMissingProperties"; + /** + * Specifies an OGNL expression cache factory implementation. A default implementation is provided, but + * could be replaced by a custom one if desired. + * + * @since 6.0.0 + */ + public static final String STRUTS_OGNL_EXPRESSION_CACHE_FACTORY = "struts.ognl.expressionCacheFactory"; + + /** + * Specifies an OGNL BeanInfo cache factory implementation. A default implementation is provided, but + * could be replaced by a custom one if desired. + * + * @since 6.0.0 + */ + public static final String STRUTS_OGNL_BEANINFO_CACHE_FACTORY = "struts.ognl.beanInfoCacheFactory"; + + /** + * Specifies the type of cache to use for BeanInfo objects. + * + * @see StrutsConstants#STRUTS_OGNL_EXPRESSION_CACHE_TYPE + * @since 6.4.0 + */ + public static final String STRUTS_OGNL_BEANINFO_CACHE_TYPE = "struts.ognl.beanInfoCacheType"; + + /** + * Specifies the maximum cache size for BeanInfo objects. This should be configured based on the cache type chosen + * and application-specific needs. + * + * @since 6.0.0 + */ + public static final String STRUTS_OGNL_BEANINFO_CACHE_MAXSIZE = "struts.ognl.beanInfoCacheMaxSize"; + + /** + * Logs properties that are not found (very verbose) + * + * @since 6.0.0 + */ + public static final String STRUTS_OGNL_LOG_MISSING_PROPERTIES = "struts.ognl.logMissingProperties"; + + /** + * Determines whether lookups on the ValueStack should fallback to looking in the context if the OGNL expression + * fails or returns null. + * + * @since 6.4.0 + */ + public static final String STRUTS_OGNL_VALUE_STACK_FALLBACK_TO_CONTEXT = "struts.ognl.valueStackFallbackToContext"; + + /** + * Enables caching of parsed OGNL expressions + * + * @since 6.0.0 + */ + public static final String STRUTS_OGNL_ENABLE_EXPRESSION_CACHE = "struts.ognl.enableExpressionCache"; + + /** + * Specifies the type of cache to use for parsed OGNL expressions. Valid values defined in + * {@link org.apache.struts2.ognl.OgnlCacheFactory.CacheType}. + *
      + *
    • For the W-TinyLfu cache, the eviction policy is detailed + * here.
    • + *
    • For the basic cache, exceeding the maximum cache size will cause the entire cache to flush.
    • + *
    • For the LRU cache, once the maximum cache size is reached, the least-recently-used entry will be removed. + *
    • + *
    + * + * @since 6.4.0 + */ + public static final String STRUTS_OGNL_EXPRESSION_CACHE_TYPE = "struts.ognl.expressionCacheType"; + + /** + * Specifies the maximum cache size for parsed OGNL expressions. This should be configured based on the cache type + * chosen and application-specific needs. + * + * @since 6.0.0 + */ + public static final String STRUTS_OGNL_EXPRESSION_CACHE_MAXSIZE = "struts.ognl.expressionCacheMaxSize"; + + /** + * Enables evaluation of OGNL expressions + * + * @since 6.0.0 + */ + public static final String STRUTS_OGNL_ENABLE_EVAL_EXPRESSION = "struts.ognl.enableEvalExpression"; - /** Enables caching of parsed OGNL expressions **/ - public static final String STRUTS_ENABLE_OGNL_EXPRESSION_CACHE = "struts.ognl.enableExpressionCache"; + /** + * The maximum length of an expression (OGNL) + */ + public static final String STRUTS_OGNL_EXPRESSION_MAX_LENGTH = "struts.ognl.expressionMaxLength"; - /** Enables evaluation of OGNL expressions **/ - public static final String STRUTS_ENABLE_OGNL_EVAL_EXPRESSION = "struts.ognl.enableOGNLEvalExpression"; + /** + * Parsed OGNL expressions which contain these node types will be blocked + */ + public static final String STRUTS_OGNL_EXCLUDED_NODE_TYPES = "struts.ognl.excludedNodeTypes"; - /** Disables {@link org.apache.struts2.dispatcher.StrutsRequestWrapper} request attribute value stack lookup (JSTL accessibility) **/ + /** + * Disables {@link org.apache.struts2.dispatcher.StrutsRequestWrapper} request attribute value stack lookup (JSTL accessibility) + */ public static final String STRUTS_DISABLE_REQUEST_ATTRIBUTE_VALUE_STACK_LOOKUP = "struts.disableRequestAttributeValueStackLookup"; - /** The{@link org.apache.struts2.views.util.UrlHelper} implementation class **/ + /** + * The{@link org.apache.struts2.views.util.UrlHelper} implementation class + */ public static final String STRUTS_URL_HELPER = "struts.view.urlHelper"; - /** {@link com.opensymphony.xwork2.conversion.impl.XWorkBasicConverter} **/ + /** + * {@link org.apache.struts2.conversion.impl.XWorkBasicConverter} + */ public static final String STRUTS_CONVERTER_COLLECTION = "struts.converter.collection"; public static final String STRUTS_CONVERTER_ARRAY = "struts.converter.array"; public static final String STRUTS_CONVERTER_DATE = "struts.converter.date"; public static final String STRUTS_CONVERTER_NUMBER = "struts.converter.number"; public static final String STRUTS_CONVERTER_STRING = "struts.converter.string"; - /** Enable handling exceptions by Dispatcher - true by default **/ + /** + * Enable handling exceptions by Dispatcher - true by default + */ public static final String STRUTS_HANDLE_EXCEPTION = "struts.handle.exception"; public static final String STRUTS_CONVERTER_PROPERTIES_PROCESSOR = "struts.converter.properties.processor"; public static final String STRUTS_CONVERTER_FILE_PROCESSOR = "struts.converter.file.processor"; public static final String STRUTS_CONVERTER_ANNOTATION_PROCESSOR = "struts.converter.annotation.processor"; public static final String STRUTS_CONVERTER_CREATOR = "struts.converter.creator"; - public static final String STRUTS_CONVERTER_HOLDER = "struts..converter.holder"; + public static final String STRUTS_CONVERTER_HOLDER = "struts.converter.holder"; public static final String STRUTS_EXPRESSION_PARSER = "struts.expression.parser"; - /** actions names' whitelist **/ + /** + * Namespace names' whitelist + */ + public static final String STRUTS_ALLOWED_NAMESPACE_NAMES = "struts.allowed.namespace.names"; + /** + * Default namespace name to use when namespace didn't match the whitelist + */ + public static final String STRUTS_DEFAULT_NAMESPACE_NAME = "struts.default.namespace.name"; + + /** + * Action names' whitelist + */ public static final String STRUTS_ALLOWED_ACTION_NAMES = "struts.allowed.action.names"; - /** default action name to use when action didn't match the whitelist **/ + /** + * Default action name to use when action didn't match the whitelist + */ public static final String STRUTS_DEFAULT_ACTION_NAME = "struts.default.action.name"; - /** methods names' whitelist **/ + /** + * Method names' whitelist + */ public static final String STRUTS_ALLOWED_METHOD_NAMES = "struts.allowed.method.names"; - /** default method name to use when method didn't match the whitelist **/ + /** + * Default method name to use when method didn't match the whitelist + */ public static final String STRUTS_DEFAULT_METHOD_NAME = "struts.default.method.name"; - /** enables action: prefix **/ + /** + * Enables action: prefix + */ public static final String STRUTS_MAPPER_ACTION_PREFIX_ENABLED = "struts.mapper.action.prefix.enabled"; - /** enables access to actions in other namespaces than current with action: prefix **/ - public static final String STRUTS_MAPPER_ACTION_PREFIX_CROSSNAMESPACES = "struts.mapper.action.prefix.crossNamespaces"; - public static final String DEFAULT_TEMPLATE_TYPE_CONFIG_KEY = "struts.ui.templateSuffix"; - /** Allows override default DispatcherErrorHandler **/ + /** + * Allows override default DispatcherErrorHandler + */ public static final String STRUTS_DISPATCHER_ERROR_HANDLER = "struts.dispatcher.errorHandler"; - /** Comma delimited set of excluded classes and package names which cannot be accessed via expressions **/ + /** + * Comma delimited set of excluded classes which cannot be accessed via OGNL expressions. Matching is done on both target and member classes of OGNL expression. Note that superclasses of listed classes are also used for matching. + */ public static final String STRUTS_EXCLUDED_CLASSES = "struts.excludedClasses"; + /** + * Comma delimited set of RegEx to match against package names of target and member classes of OGNL expressions. If matched, they cannot be accessed. + */ public static final String STRUTS_EXCLUDED_PACKAGE_NAME_PATTERNS = "struts.excludedPackageNamePatterns"; + /** + * Comma delimited set of package names, of which all its classes, and all classes in its subpackages, cannot be accessed via OGNL expressions. Matching is done on both target and member classes of OGNL expression. + */ public static final String STRUTS_EXCLUDED_PACKAGE_NAMES = "struts.excludedPackageNames"; + /** + * Comma delimited set of exempt classes from matching against excludedPackageNames and excludedPackageNamePatterns. As matching for excluded packages is done on both target and member classes of OGNL expression, an exemption must exist for each match. + */ + public static final String STRUTS_EXCLUDED_PACKAGE_EXEMPT_CLASSES = "struts.excludedPackageExemptClasses"; - /** Dedicated services to check if passed string is excluded/accepted **/ + /** + * Comma delimited set of excluded classes and package names which cannot be accessed via expressions in devMode + */ + public static final String STRUTS_DEV_MODE_EXCLUDED_CLASSES = "struts.devMode.excludedClasses"; + public static final String STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAME_PATTERNS = "struts.devMode.excludedPackageNamePatterns"; + public static final String STRUTS_DEV_MODE_EXCLUDED_PACKAGE_NAMES = "struts.devMode.excludedPackageNames"; + public static final String STRUTS_DEV_MODE_EXCLUDED_PACKAGE_EXEMPT_CLASSES = "struts.devMode.excludedPackageExemptClasses"; + + /** + * Boolean to enable strict allowlist processing of all OGNL expression calls. + */ + public static final String STRUTS_ALLOWLIST_ENABLE = "struts.allowlist.enable"; + /** + * Comma delimited set of allowed classes which CAN be accessed via OGNL expressions. Both target and member classes of OGNL expression must be allowlisted. + */ + public static final String STRUTS_ALLOWLIST_CLASSES = "struts.allowlist.classes"; + /** + * Comma delimited set of package names, of which all its classes, and all classes in its subpackages, CAN be accessed via OGNL expressions. Both target and member classes of OGNL expression must be allowlisted. + */ + public static final String STRUTS_ALLOWLIST_PACKAGE_NAMES = "struts.allowlist.packageNames"; + + /** + * Dedicated services to check if passed string is excluded/accepted + */ public static final String STRUTS_EXCLUDED_PATTERNS_CHECKER = "struts.excludedPatterns.checker"; public static final String STRUTS_ACCEPTED_PATTERNS_CHECKER = "struts.acceptedPatterns.checker"; + public static final String STRUTS_NOT_EXCLUDED_ACCEPTED_PATTERNS_CHECKER = "struts.notExcludedAcceptedPatterns.checker"; - /** Constant is used to override framework's default excluded patterns **/ + /** + * Constant is used to override framework's default excluded patterns + */ public static final String STRUTS_OVERRIDE_EXCLUDED_PATTERNS = "struts.override.excludedPatterns"; public static final String STRUTS_OVERRIDE_ACCEPTED_PATTERNS = "struts.override.acceptedPatterns"; public static final String STRUTS_ADDITIONAL_EXCLUDED_PATTERNS = "struts.additional.excludedPatterns"; public static final String STRUTS_ADDITIONAL_ACCEPTED_PATTERNS = "struts.additional.acceptedPatterns"; + public static final String STRUTS_PARAMETERS_REQUIRE_ANNOTATIONS = "struts.parameters.requireAnnotations"; + public static final String STRUTS_PARAMETERS_REQUIRE_ANNOTATIONS_TRANSITION = "struts.parameters.requireAnnotations.transitionMode"; + public static final String STRUTS_CONTENT_TYPE_MATCHER = "struts.contentTypeMatcher"; public static final String STRUTS_SMI_METHOD_REGEX = "struts.strictMethodInvocation.methodRegex"; + public static final String STRUTS_TEXT_PROVIDER = "struts.textProvider"; public static final String STRUTS_TEXT_PROVIDER_FACTORY = "struts.textProviderFactory"; - public static final String STRUTS_LOCALIZED_TEXT_PROVIDER = "struts.localizedTextProvider"; + + public static final String STRUTS_DISALLOW_PROXY_OBJECT_ACCESS = "struts.disallowProxyObjectAccess"; + public static final String STRUTS_DISALLOW_PROXY_MEMBER_ACCESS = "struts.disallowProxyMemberAccess"; + public static final String STRUTS_DISALLOW_DEFAULT_PACKAGE_ACCESS = "struts.disallowDefaultPackageAccess"; + + public static final String STRUTS_OGNL_AUTO_GROWTH_COLLECTION_LIMIT = "struts.ognl.autoGrowthCollectionLimit"; + + /** + * See {@link org.apache.struts2.config.impl.AbstractMatcher#appendNamedParameters + */ + public static final String STRUTS_MATCHER_APPEND_NAMED_PARAMETERS = "struts.matcher.appendNamedParameters"; + + public static final String STRUTS_CHAINING_COPY_ERRORS = "struts.chaining.copyErrors"; + public static final String STRUTS_CHAINING_COPY_FIELD_ERRORS = "struts.chaining.copyFieldErrors"; + public static final String STRUTS_CHAINING_COPY_MESSAGES = "struts.chaining.copyMessages"; + public static final String STRUTS_OBJECT_FACTORY_CLASSLOADER = "struts.objectFactory.classloader"; + + /** + * See {@link org.apache.struts2.components.Date#setDateFormatter(DateFormatter)} + */ + public static final String STRUTS_DATE_FORMATTER = "struts.date.formatter"; + + public static final String STRUTS_URL_QUERY_STRING_BUILDER = "struts.url.queryStringBuilder"; + public static final String STRUTS_URL_QUERY_STRING_PARSER = "struts.url.queryStringParser"; + public static final String STRUTS_URL_ENCODER = "struts.url.encoder"; + public static final String STRUTS_URL_DECODER = "struts.url.decoder"; + + /** + * A global flag to set property {@link org.apache.struts2.components.Checkbox#setSubmitUnchecked(String)} + */ + public static final String STRUTS_UI_CHECKBOX_SUBMIT_UNCHECKED = "struts.ui.checkbox.submitUnchecked"; + + /** + * See {@link org.apache.struts2.interceptor.exec.ExecutorProvider} + */ + public static final String STRUTS_EXECUTOR_PROVIDER = "struts.executor.provider"; } diff --git a/core/src/main/java/org/apache/struts2/StrutsException.java b/core/src/main/java/org/apache/struts2/StrutsException.java index 089205aa6a..aad0223828 100644 --- a/core/src/main/java/org/apache/struts2/StrutsException.java +++ b/core/src/main/java/org/apache/struts2/StrutsException.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,20 +16,18 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2; -import com.opensymphony.xwork2.XWorkException; -import com.opensymphony.xwork2.util.location.Locatable; - +import org.apache.struts2.util.location.Locatable; +import org.apache.struts2.util.location.Location; +import org.apache.struts2.util.location.LocationUtils; /** * A generic runtime exception that optionally contains Location information */ -public class StrutsException extends XWorkException implements Locatable { - - private static final long serialVersionUID = 888724366243600135L; +public class StrutsException extends RuntimeException implements Locatable { + private Location location; /** * Constructs a StrutsException with no detail message. @@ -57,7 +53,7 @@ public StrutsException(String s) { * @param target the target of the exception. */ public StrutsException(String s, Object target) { - this(s, (Throwable) null, target); + this(s, null, target); } /** @@ -100,6 +96,45 @@ public StrutsException(String s, Throwable cause) { * @param target The target of the exception */ public StrutsException(String s, Throwable cause, Object target) { - super(s, cause, target); + super(s, cause); + + this.location = LocationUtils.getLocation(target); + if (this.location == Location.UNKNOWN) { + this.location = LocationUtils.getLocation(cause); + } + } + + /** + * Gets the location of the error, if available + * + * @return the location, null if not available + */ + public Location getLocation() { + return this.location; + } + + /** + * Returns a short description of this throwable object, including the + * location. If no detailed message is available, it will use the message + * of the underlying exception if available. + * + * @return a string representation of this Throwable. + */ + @Override + public String toString() { + String msg = getMessage(); + if (msg == null && getCause() != null) { + msg = getCause().getMessage(); + } + + if (location != null) { + if (msg != null) { + return msg + " - " + location; + } else { + return location.toString(); + } + } else { + return msg; + } } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/apache/struts2/StrutsStatics.java b/core/src/main/java/org/apache/struts2/StrutsStatics.java index d204f52734..6ff9322261 100644 --- a/core/src/main/java/org/apache/struts2/StrutsStatics.java +++ b/core/src/main/java/org/apache/struts2/StrutsStatics.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,26 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2; +import jakarta.servlet.ServletContext; /** *

    - * Constants used by Struts. The constants can be used to get or set objects - * out of the action context or other collections. - *

    - * - *

    - * Example: - * - * ActionContext.getContext().put(HTTP_REQUEST, request); - * - * or - * - * - * ActionContext context = ActionContext.getContext();
    - * HttpServletRequest request = (HttpServletRequest)context.get(HTTP_REQUEST);
    + * Constants used internally by Struts. Do not use these constants directly, + * instead use exposed helpers eg.: {@link org.apache.struts2.dispatcher.Dispatcher#getInstance(ServletContext)} *

    */ public interface StrutsStatics { @@ -45,34 +31,33 @@ public interface StrutsStatics { /** * Constant for the HTTP request object. */ - public static final String HTTP_REQUEST = "com.opensymphony.xwork2.dispatcher.HttpServletRequest"; + String HTTP_REQUEST = "org.apache.struts2.dispatcher.HttpServletRequest"; /** * Constant for the HTTP response object. */ - public static final String HTTP_RESPONSE = "com.opensymphony.xwork2.dispatcher.HttpServletResponse"; + String HTTP_RESPONSE = "org.apache.struts2.dispatcher.HttpServletResponse"; /** - * Constant for an HTTP {@link javax.servlet.RequestDispatcher request dispatcher}. + * Constant for an HTTP {@link jakarta.servlet.RequestDispatcher request dispatcher}. */ - public static final String SERVLET_DISPATCHER = "com.opensymphony.xwork2.dispatcher.ServletDispatcher"; + String SERVLET_DISPATCHER = "org.apache.struts2.dispatcher.ServletDispatcher"; /** - * Constant for the {@link javax.servlet.ServletContext servlet context} object. + * Constant for the {@link jakarta.servlet.ServletContext servlet context} object. */ - public static final String SERVLET_CONTEXT = "com.opensymphony.xwork2.dispatcher.ServletContext"; + String SERVLET_CONTEXT = "org.apache.struts2.dispatcher.ServletContext"; /** - * Constant for the JSP {@link javax.servlet.jsp.PageContext page context}. + * Constant for the JSP {@link jakarta.servlet.jsp.PageContext page context}. */ - public static final String PAGE_CONTEXT = "com.opensymphony.xwork2.dispatcher.PageContext"; - - /** Constant for the PortletContext object */ - public static final String STRUTS_PORTLET_CONTEXT = "struts.portlet.context"; + String PAGE_CONTEXT = "org.apache.struts2.dispatcher.PageContext"; /** * Set as an attribute in the request to let other parts of the framework know that the invocation is happening inside an * action tag */ - public static final String STRUTS_ACTION_TAG_INVOCATION= "struts.actiontag.invocation"; + String STRUTS_ACTION_TAG_INVOCATION = "struts.actiontag.invocation"; + + String ACTION_MAPPING = "struts.actionMapping"; } diff --git a/core/src/main/java/org/apache/struts2/Unchainable.java b/core/src/main/java/org/apache/struts2/Unchainable.java new file mode 100644 index 0000000000..5ff75b0d99 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/Unchainable.java @@ -0,0 +1,27 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2; + +/** + * Simple marker interface to indicate an object should not have its properties copied during chaining. + * + * @see org.apache.struts2.interceptor.ChainingInterceptor + */ +public interface Unchainable { +} diff --git a/core/src/main/java/org/apache/struts2/UnknownHandler.java b/core/src/main/java/org/apache/struts2/UnknownHandler.java new file mode 100644 index 0000000000..97883cb97c --- /dev/null +++ b/core/src/main/java/org/apache/struts2/UnknownHandler.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.struts2; + +import org.apache.struts2.config.entities.ActionConfig; +import org.apache.struts2.result.Result; + +/** + * Handles cases when the result or action is unknown. + * + *

    + * This allows other classes like Struts plugins to provide intelligent defaults easier. + *

    + */ +public interface UnknownHandler { + + /** + * Handles the case when an action configuration is unknown. Implementations can return a new ActionConfig + * to be used to process the request. + * + * @param namespace The namespace + * @param actionName The action name + * @return An generated ActionConfig, can return null + * @throws StrutsException in case of errors + */ + ActionConfig handleUnknownAction(String namespace, String actionName) throws StrutsException; + + /** + * Handles the case when a result cannot be found for an action and result code. + * + * @param actionContext The action context + * @param actionName The action name + * @param actionConfig The action config + * @param resultCode The returned result code + * @return A result to be executed, can return null + * @throws StrutsException in case of errors + */ + Result handleUnknownResult(ActionContext actionContext, String actionName, ActionConfig actionConfig, String resultCode) throws StrutsException; + + /** + * Handles the case when an action method cannot be found. This method is responsible both for finding the method and executing it. + * + * @since 2.1 + * @param action The action object + * @param methodName The method name to call + * @return The result returned from invoking the action method, can return null if this instance cannot + * handle such methodName to allow other handlers give a chance + */ + Object handleUnknownActionMethod(Object action, String methodName); + +} diff --git a/core/src/main/java/org/apache/struts2/UnknownHandlerManager.java b/core/src/main/java/org/apache/struts2/UnknownHandlerManager.java new file mode 100644 index 0000000000..657cebe352 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/UnknownHandlerManager.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.struts2; + +import org.apache.struts2.config.entities.ActionConfig; +import org.apache.struts2.result.Result; + +import java.util.List; + +/** + * An unknown handler manager contains a list of UnknownHandler and iterates on them by order + * + * @see org.apache.struts2.DefaultUnknownHandlerManager + */ +public interface UnknownHandlerManager { + + Result handleUnknownResult(ActionContext actionContext, String actionName, ActionConfig actionConfig, String resultCode); + + /** + * Tries to handle passed methodName if cannot find method should re + * + * @param action Action's instance + * @param methodName method name to handle + * @return Result representing result of given action method + * @throws NoSuchMethodException if method can be handled by defined UnknownHandlers + */ + Object handleUnknownMethod(Object action, String methodName) throws NoSuchMethodException; + + ActionConfig handleUnknownAction(String namespace, String actionName); + + boolean hasUnknownHandlers(); + + List getUnknownHandlers(); + +} diff --git a/core/src/main/java/org/apache/struts2/Validateable.java b/core/src/main/java/org/apache/struts2/Validateable.java new file mode 100644 index 0000000000..16f52670ab --- /dev/null +++ b/core/src/main/java/org/apache/struts2/Validateable.java @@ -0,0 +1,35 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2; + +/** + * Provides an interface in which a call for a validation check can be done. + * + * @author Jason Carreira + * @see ActionSupport + * @see org.apache.struts2.interceptor.DefaultWorkflowInterceptor + */ +public interface Validateable { + + /** + * Performs validation. + */ + void validate(); + +} diff --git a/core/src/main/java/com/opensymphony/xwork2/ValidationAwareSupport.java b/core/src/main/java/org/apache/struts2/ValidationAwareSupport.java similarity index 78% rename from core/src/main/java/com/opensymphony/xwork2/ValidationAwareSupport.java rename to core/src/main/java/org/apache/struts2/ValidationAwareSupport.java index 2f64a987a1..d014189399 100644 --- a/core/src/main/java/com/opensymphony/xwork2/ValidationAwareSupport.java +++ b/core/src/main/java/org/apache/struts2/ValidationAwareSupport.java @@ -1,24 +1,32 @@ /* - * Copyright 2002-2006,2009 The Apache Software Foundation. - * - * 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. + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. */ -package com.opensymphony.xwork2; +package org.apache.struts2; -import com.opensymphony.xwork2.interceptor.ValidationAware; +import org.apache.struts2.interceptor.ValidationAware; import java.io.Serializable; -import java.util.*; +import java.util.ArrayList; +import java.util.Collection; +import java.util.LinkedHashMap; +import java.util.LinkedList; +import java.util.List; +import java.util.Map; /** * Provides a default implementation of ValidationAware. Returns new collections for @@ -69,13 +77,7 @@ public synchronized void addActionMessage(String aMessage) { public synchronized void addFieldError(String fieldName, String errorMessage) { final Map> errors = internalGetFieldErrors(); - List thisFieldErrors = errors.get(fieldName); - - if (thisFieldErrors == null) { - thisFieldErrors = new ArrayList<>(); - errors.put(fieldName, thisFieldErrors); - } - + List thisFieldErrors = errors.computeIfAbsent(fieldName, k -> new ArrayList<>()); thisFieldErrors.add(errorMessage); } diff --git a/core/src/main/java/org/apache/struts2/XWorkJUnit4TestCase.java b/core/src/main/java/org/apache/struts2/XWorkJUnit4TestCase.java new file mode 100644 index 0000000000..96afc8a4e1 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/XWorkJUnit4TestCase.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.struts2; + +import org.apache.struts2.config.Configuration; +import org.apache.struts2.config.ConfigurationException; +import org.apache.struts2.config.ConfigurationManager; +import org.apache.struts2.config.ConfigurationProvider; +import org.apache.struts2.inject.Container; +import org.apache.struts2.inject.ContainerBuilder; +import org.apache.struts2.inject.Context; +import org.apache.struts2.inject.Factory; +import org.apache.struts2.inject.Scope; +import org.apache.struts2.test.StubConfigurationProvider; +import org.apache.struts2.util.XWorkTestCaseHelper; +import org.apache.struts2.util.location.LocatableProperties; +import org.junit.After; +import org.junit.Before; + +public abstract class XWorkJUnit4TestCase { + + protected ConfigurationManager configurationManager; + protected Configuration configuration; + protected Container container; + protected ActionProxyFactory actionProxyFactory; + + @Before + public void setUp() throws Exception { + configurationManager = XWorkTestCaseHelper.setUp(); + configuration = configurationManager.getConfiguration(); + container = configuration.getContainer(); + actionProxyFactory = container.getInstance(ActionProxyFactory.class); + } + + @After + public void tearDown() throws Exception { + XWorkTestCaseHelper.tearDown(configurationManager); + } + + protected void loadConfigurationProviders(ConfigurationProvider... providers) { + configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers); + configuration = configurationManager.getConfiguration(); + container = configuration.getContainer(); + actionProxyFactory = container.getInstance(ActionProxyFactory.class); + } + + protected void loadButAdd(final Class type, final Object impl) { + loadButAdd(type, Container.DEFAULT_NAME, impl); + } + + protected void loadButAdd(final Class type, final String name, final Object impl) { + loadConfigurationProviders(new StubConfigurationProvider() { + @Override + public void register(ContainerBuilder builder, + LocatableProperties props) throws ConfigurationException { + builder.factory(type, name, new Factory() { + public Object create(Context context) throws Exception { + return impl; + } + + @Override + public Class type() { + return impl.getClass(); + } + }, Scope.SINGLETON); + } + }); + } + +} diff --git a/core/src/main/java/org/apache/struts2/XWorkTestCase.java b/core/src/main/java/org/apache/struts2/XWorkTestCase.java new file mode 100644 index 0000000000..fa31ea77b5 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/XWorkTestCase.java @@ -0,0 +1,144 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2; + +import org.apache.struts2.config.Configuration; +import org.apache.struts2.config.ConfigurationException; +import org.apache.struts2.config.ConfigurationManager; +import org.apache.struts2.config.ConfigurationProvider; +import org.apache.struts2.inject.Container; +import org.apache.struts2.inject.ContainerBuilder; +import org.apache.struts2.inject.Context; +import org.apache.struts2.inject.Factory; +import org.apache.struts2.inject.Scope; +import org.apache.struts2.test.StubConfigurationProvider; +import org.apache.struts2.util.XWorkTestCaseHelper; +import org.apache.struts2.util.location.LocatableProperties; +import junit.framework.TestCase; +import org.apache.commons.lang3.ClassUtils; + +import java.util.Locale; +import java.util.Map; + +import static java.util.Collections.singletonMap; + +/** + * Base JUnit TestCase to extend for XWork specific JUnit tests. Uses + * the generic test setup for logic. + * + * @author plightbo + */ +public abstract class XWorkTestCase extends TestCase { + + protected ConfigurationManager configurationManager; + protected Configuration configuration; + protected Container container; + protected ActionProxyFactory actionProxyFactory; + + public XWorkTestCase() { + super(); + } + + @Override + protected void setUp() throws Exception { + configurationManager = XWorkTestCaseHelper.setUp(); + reloadConfiguration(configurationManager); + } + + @Override + protected void tearDown() throws Exception { + XWorkTestCaseHelper.tearDown(configurationManager); + } + + private void reloadConfiguration(ConfigurationManager configurationManager) { + configuration = configurationManager.getConfiguration(); + container = configuration.getContainer(); + actionProxyFactory = container.getInstance(ActionProxyFactory.class); + } + + protected void loadConfigurationProviders(ConfigurationProvider... providers) { + configurationManager = XWorkTestCaseHelper.loadConfigurationProviders(configurationManager, providers); + reloadConfiguration(configurationManager); + } + + protected void loadButSet(Map properties) { + loadConfigurationProviders(new StubConfigurationProvider() { + @Override + public void register(ContainerBuilder builder, + LocatableProperties props) throws ConfigurationException { + properties.forEach((k, v) -> props.setProperty(k, String.valueOf(v))); + } + }); + } + + protected void loadButAdd(final Class type, final T impl) { + loadButAdd(type, Container.DEFAULT_NAME, impl); + } + + protected void loadButAdd(final Class type, final String name, final T impl) { + loadConfigurationProviders(new StubConfigurationProvider() { + @Override + public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { + if (impl instanceof String || ClassUtils.isPrimitiveOrWrapper(impl.getClass())) { + props.setProperty(name, "" + impl); + } else { + builder.factory(type, name, new Factory<>() { + @Override + public T create(Context context) throws Exception { + return impl; + } + + @Override + public Class type() { + return (Class) impl.getClass(); + } + }, Scope.SINGLETON); + } + } + }); + } + + protected Map createContextWithLocale(Locale locale) { + return ActionContext.of() + .withLocale(locale) + .getContextMap(); + } + + protected void setStrutsConstant(String constant, String value) { + setStrutsConstant(singletonMap(constant, value)); + } + + protected void setStrutsConstant(final Map overwritePropeties) { + configurationManager.addContainerProvider(new StubConfigurationProvider() { + @Override + public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException { + for (Map.Entry stringStringEntry : overwritePropeties.entrySet()) { + props.setProperty(stringStringEntry.getKey(), stringStringEntry.getValue(), null); + } + } + + @Override + public void destroy() { + } + }); + + configurationManager.reload(); + reloadConfiguration(configurationManager); + } +} diff --git a/core/src/main/java/org/apache/struts2/action/Action.java b/core/src/main/java/org/apache/struts2/action/Action.java new file mode 100644 index 0000000000..11064054bd --- /dev/null +++ b/core/src/main/java/org/apache/struts2/action/Action.java @@ -0,0 +1,88 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.action; + +/** + * All actions may implement this interface, which exposes the execute() method. + *

    + * However, as of XWork 1.1, this is not required and is only here to assist users. You are free to create POJOs + * that honor the same contract defined by this interface without actually implementing the interface. + *

    + */ +public interface Action { + + /** + * The action execution was successful. Show result + * view to the end user. + */ + String SUCCESS = "success"; + + /** + * The action execution was successful but do not + * show a view. This is useful for actions that are + * handling the view in another fashion like redirect. + */ + String NONE = "none"; + + /** + * The action execution was a failure. + * Show an error view, possibly asking the + * user to retry entering data. + */ + String ERROR = "error"; + + /** + *

    + * The action execution require more input + * in order to succeed. + * This result is typically used if a form + * handling action has been executed so as + * to provide defaults for a form. The + * form associated with the handler should be + * shown to the end user. + *

    + * + *

    + * This result is also used if the given input + * params are invalid, meaning the user + * should try providing input again. + *

    + */ + String INPUT = "input"; + + /** + * The action could not execute, since the + * user most was not logged in. The login view + * should be shown. + */ + String LOGIN = "login"; + + + /** + * Where the logic of the action is executed. + * + * @return a string representing the logical result of the execution. + * See constants in this interface for a list of standard result values. + * @throws Exception thrown if a system level exception occurs. + * Note: Application level exceptions should be handled by returning + * an error value, such as Action.ERROR. + */ + String execute() throws Exception; + +} diff --git a/core/src/main/java/org/apache/struts2/interceptor/ApplicationAware.java b/core/src/main/java/org/apache/struts2/action/ApplicationAware.java similarity index 85% rename from core/src/main/java/org/apache/struts2/interceptor/ApplicationAware.java rename to core/src/main/java/org/apache/struts2/action/ApplicationAware.java index a68608638f..3748e60f22 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/ApplicationAware.java +++ b/core/src/main/java/org/apache/struts2/action/ApplicationAware.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,28 +16,23 @@ * specific language governing permissions and limitations * under the License. */ - -package org.apache.struts2.interceptor; +package org.apache.struts2.action; import java.util.Map; - /** - *

    * Actions that want to be aware of the application Map object should implement this interface. * This will give them access to a Map where they can put objects that should be available * to other parts of the application. - *

    - *

    + * * Typical uses are configuration objects and caches. - *

    */ public interface ApplicationAware { /** - * Sets the map of application properties in the implementing class. + * Applies the map of application properties in the implementing class. * * @param application a Map of application properties. */ - public void setApplication(Map application); + void withApplication(Map application); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/CookiesAware.java b/core/src/main/java/org/apache/struts2/action/CookiesAware.java similarity index 88% rename from core/src/main/java/org/apache/struts2/interceptor/CookiesAware.java rename to core/src/main/java/org/apache/struts2/action/CookiesAware.java index a4d029d0a4..487c961abf 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/CookiesAware.java +++ b/core/src/main/java/org/apache/struts2/action/CookiesAware.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,8 +16,9 @@ * specific language governing permissions and limitations * under the License. */ +package org.apache.struts2.action; -package org.apache.struts2.interceptor; +import org.apache.struts2.interceptor.CookieInterceptor; import java.util.Map; @@ -29,11 +28,13 @@ * * Please note that the {@link CookieInterceptor} needs to be * activated to receive a cookies map. + * + * @since 6.0.0 */ public interface CookiesAware { /** * Sets a map of filtered cookies. * @param cookies the cookies */ - void setCookiesMap(Map cookies); -} \ No newline at end of file + void withCookies(Map cookies); +} diff --git a/core/src/main/java/org/apache/struts2/action/CspReportAction.java b/core/src/main/java/org/apache/struts2/action/CspReportAction.java new file mode 100644 index 0000000000..c8b6b7bc51 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/action/CspReportAction.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.struts2.action; + +import org.apache.struts2.ActionSupport; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import java.io.BufferedReader; +import java.io.IOException; + +import static org.apache.struts2.interceptor.csp.CspSettings.CSP_REPORT_TYPE; + +/** + * An abstract Action that can be extended to process the incoming CSP violation reports. Performs + * necessary checks to extract the JSON string of the CSP report and make sure it's a valid report. + * Always returns a 204 response. + * + * Override the processReport(String jsonCspReport) method to customize how the action processes + * the CSP report. See {@link DefaultCspReportAction} for the default implementation. + * + * Add the action to the endpoint that is the reportUri in the {@link org.apache.struts2.interceptor.csp.CspInterceptor} + * to collect the reports. + * + *
    + *     <package name="csp-reports" namespace="/" extends="struts-default">
    + *         <action name="csp-reports" class="org.apache.struts2.action.DefaultCspReportAction">
    + *             <result type="httpheader">
    + *                 <param name="status">204</param>
    + *             </result>
    + *         </action>
    + *     </package>
    + * 
    + * + * @see DefaultCspReportAction + */ +public abstract class CspReportAction extends ActionSupport implements ServletRequestAware, ServletResponseAware { + private HttpServletRequest request; + + @Override + public void withServletRequest(HttpServletRequest request) { + if (!isCspReportRequest(request)) { + return; + } + + try { + BufferedReader reader = request.getReader(); + String cspReport = reader.readLine(); + processReport(cspReport); + } catch (IOException ignored) { + } + } + + private boolean isCspReportRequest(HttpServletRequest request) { + if (!"POST".equals(request.getMethod()) || request.getContentLength() <= 0){ + return false; + } + + String contentType = request.getContentType(); + return CSP_REPORT_TYPE.equals(contentType); + } + + @Override + public void withServletResponse(HttpServletResponse response) { + response.setStatus(204); + } + + abstract void processReport(String jsonCspReport); + + public void setServletRequest(HttpServletRequest request) { + this.request = request; + } + + public HttpServletRequest getServletRequest() { + return request; + } +} diff --git a/core/src/main/java/org/apache/struts2/action/CspSettingsAware.java b/core/src/main/java/org/apache/struts2/action/CspSettingsAware.java new file mode 100644 index 0000000000..458a7c7f39 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/action/CspSettingsAware.java @@ -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. + */ +package org.apache.struts2.action; + +import org.apache.struts2.interceptor.csp.CspSettings; + +/** + * Implement this interface by an action to provide a custom {@link CspSettings}, + * see {@link org.apache.struts2.interceptor.csp.CspInterceptor} for more details + * + * @since Struts 6.2.0 + */ +public interface CspSettingsAware { + + CspSettings getCspSettings(); + +} diff --git a/core/src/main/java/org/apache/struts2/action/DefaultCspReportAction.java b/core/src/main/java/org/apache/struts2/action/DefaultCspReportAction.java new file mode 100644 index 0000000000..3bae9f0ee8 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/action/DefaultCspReportAction.java @@ -0,0 +1,38 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.action; + +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; + +/** + * The default implementation of {@link CspReportAction} that simply logs the JSON object + * that contains the details of the CSP violation. + * + * @see CspReportAction + */ +public class DefaultCspReportAction extends CspReportAction { + + protected static final Logger LOG = LogManager.getLogger(DefaultCspReportAction.class); + + @Override + void processReport(String jsonCspReport) { + LOG.error(jsonCspReport); + } +} diff --git a/core/src/main/java/org/apache/struts2/action/NoParameters.java b/core/src/main/java/org/apache/struts2/action/NoParameters.java new file mode 100644 index 0000000000..74e3e46866 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/action/NoParameters.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.struts2.action; + +/** + * This marker interface should be implemented by actions that do not want any parameters set on + * them automatically. This may be useful if one is using the action tag and want to supply + * the parameters to the action manually using the param tag. It may also be useful if one for + * security reasons wants to make sure that parameters cannot be set by malicious users. + */ +public interface NoParameters { +} diff --git a/core/src/main/java/org/apache/struts2/action/ParameterNameAware.java b/core/src/main/java/org/apache/struts2/action/ParameterNameAware.java new file mode 100644 index 0000000000..83a69333de --- /dev/null +++ b/core/src/main/java/org/apache/struts2/action/ParameterNameAware.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.action; + +import org.apache.struts2.interceptor.parameter.ParametersInterceptor; + +/** + * This interface is implemented by actions that want to declare acceptable parameters. Works in conjunction with {@link + * ParametersInterceptor}. For example, actions may want to create a white list of parameters they will accept or a + * blacklist of parameters they will reject to prevent clients from setting other unexpected (and possibly dangerous) + * parameters. + */ +public interface ParameterNameAware { + + /** + * Tests if the action will accept the parameter with the given name. + * + * @param parameterName the parameter name + * @return true if accepted, false otherwise + */ + boolean acceptableParameterName(String parameterName); + +} diff --git a/core/src/main/java/org/apache/struts2/action/ParameterValueAware.java b/core/src/main/java/org/apache/struts2/action/ParameterValueAware.java new file mode 100644 index 0000000000..e2f91afa82 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/action/ParameterValueAware.java @@ -0,0 +1,39 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.struts2.action; + +import org.apache.struts2.interceptor.parameter.ParametersInterceptor; + +/** + * This interface is implemented by actions that want to declare acceptable parameter values. Works in conjunction with + * {@link ParametersInterceptor}. For example, actions may want to create a white list of parameter values they will + * accept or a blacklist of parameter values they will reject to prevent clients from setting other unexpected (and + * possibly dangerous) parameter values. + */ +public interface ParameterValueAware { + + /** + * Tests if the action will accept the parameter with the given value. + * + * @param parameterValue the parameter value + * @return true if accepted, false otherwise + */ + boolean acceptableParameterValue(String parameterValue); + +} diff --git a/core/src/main/java/org/apache/struts2/action/ParametersAware.java b/core/src/main/java/org/apache/struts2/action/ParametersAware.java new file mode 100644 index 0000000000..8cbf45ef6a --- /dev/null +++ b/core/src/main/java/org/apache/struts2/action/ParametersAware.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.struts2.action; + +import org.apache.struts2.dispatcher.HttpParameters; + +/** + * This interface gives actions an alternative way of receiving input parameters. The parameters will + * contain all input parameters as implementation of {@link org.apache.struts2.dispatcher.Parameter}. + * Actions that need this should simply implement it. + * + * One common use for this is to have the action propagate parameters to internally instantiated data + * objects. + * + * @since 6.0.0 + */ +public interface ParametersAware { + + /** + * Sets the HTTP parameters in the implementing class. + * + * @param parameters an instance of {@link HttpParameters}. + */ + void withParameters(HttpParameters parameters); +} diff --git a/core/src/main/java/org/apache/struts2/interceptor/PrincipalAware.java b/core/src/main/java/org/apache/struts2/action/PrincipalAware.java similarity index 80% rename from core/src/main/java/org/apache/struts2/interceptor/PrincipalAware.java rename to core/src/main/java/org/apache/struts2/action/PrincipalAware.java index 91878d81c1..9bff42bebb 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/PrincipalAware.java +++ b/core/src/main/java/org/apache/struts2/action/PrincipalAware.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,17 +16,19 @@ * specific language governing permissions and limitations * under the License. */ +package org.apache.struts2.action; -package org.apache.struts2.interceptor; +import org.apache.struts2.interceptor.PrincipalProxy; /** * Actions that want access to the Principal information from HttpServletRequest object * should implement this interface. * - *

    This interface is only relevant if the Action is used in a servlet environment. - * By using this interface you will not become tied to servlet environment.

    - * + * This interface is only relevant if the Action is used in a servlet environment. + * By using this interface you will not become tied to servlet environment. */ public interface PrincipalAware { - void setPrincipalProxy(PrincipalProxy principalProxy); + + void withPrincipalProxy(PrincipalProxy principalProxy); + } diff --git a/core/src/main/java/org/apache/struts2/util/ServletContextAware.java b/core/src/main/java/org/apache/struts2/action/ServletContextAware.java similarity index 86% rename from core/src/main/java/org/apache/struts2/util/ServletContextAware.java rename to core/src/main/java/org/apache/struts2/action/ServletContextAware.java index 23f065465d..ec3d7ed2b3 100644 --- a/core/src/main/java/org/apache/struts2/util/ServletContextAware.java +++ b/core/src/main/java/org/apache/struts2/action/ServletContextAware.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,16 @@ * specific language governing permissions and limitations * under the License. */ +package org.apache.struts2.action; -package org.apache.struts2.util; - -import javax.servlet.ServletContext; - +import jakarta.servlet.ServletContext; /** * For components that have a dependence on the Servlet context. + * + * @since 6.0.0 */ public interface ServletContextAware { - public void setServletContext(ServletContext context); + void withServletContext(ServletContext context); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/ServletRequestAware.java b/core/src/main/java/org/apache/struts2/action/ServletRequestAware.java similarity index 82% rename from core/src/main/java/org/apache/struts2/interceptor/ServletRequestAware.java rename to core/src/main/java/org/apache/struts2/action/ServletRequestAware.java index 814864c4c0..6f166fd0e8 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/ServletRequestAware.java +++ b/core/src/main/java/org/apache/struts2/action/ServletRequestAware.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,32 +16,24 @@ * specific language governing permissions and limitations * under the License. */ +package org.apache.struts2.action; -package org.apache.struts2.interceptor; - -import javax.servlet.http.HttpServletRequest; - +import jakarta.servlet.http.HttpServletRequest; /** - *

    * All Actions that want to have access to the servlet request object must implement this interface. - *

    * - *

    * This interface is only relevant if the Action is used in a servlet environment. - *

    * - *

    * Note that using this interface makes the Action tied to a servlet environment, so it should be * avoided if possible since things like unit testing will become more difficult. - *

    */ public interface ServletRequestAware { /** - * Sets the HTTP request object in implementing classes. + * Applies the HTTP request object in implementing classes. * * @param request the HTTP request. */ - public void setServletRequest(HttpServletRequest request); + void withServletRequest(HttpServletRequest request); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/ServletResponseAware.java b/core/src/main/java/org/apache/struts2/action/ServletResponseAware.java similarity index 82% rename from core/src/main/java/org/apache/struts2/interceptor/ServletResponseAware.java rename to core/src/main/java/org/apache/struts2/action/ServletResponseAware.java index 2fa55379dc..12da41c350 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/ServletResponseAware.java +++ b/core/src/main/java/org/apache/struts2/action/ServletResponseAware.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,30 +16,24 @@ * specific language governing permissions and limitations * under the License. */ +package org.apache.struts2.action; -package org.apache.struts2.interceptor; - -import javax.servlet.http.HttpServletResponse; - +import jakarta.servlet.http.HttpServletResponse; /** - *

    * All Actions that want to have access to the servlet response object must implement this interface. - *

    - *

    + * * This interface is only relevant if the Action is used in a servlet environment. - *

    - *

    + * * Note that using this interface makes the Action tied to a servlet environment, so it should be * avoided if possible since things like unit testing will become more difficult. - *

    */ public interface ServletResponseAware { /** - * Sets the HTTP response object in implementing classes. + * Applies the HTTP response object in implementing classes. * * @param response the HTTP response. */ - public void setServletResponse(HttpServletResponse response); + void withServletResponse(HttpServletResponse response); } diff --git a/core/src/main/java/org/apache/struts2/interceptor/SessionAware.java b/core/src/main/java/org/apache/struts2/action/SessionAware.java similarity index 85% rename from core/src/main/java/org/apache/struts2/interceptor/SessionAware.java rename to core/src/main/java/org/apache/struts2/action/SessionAware.java index ea101bbfb3..039fcca00f 100644 --- a/core/src/main/java/org/apache/struts2/interceptor/SessionAware.java +++ b/core/src/main/java/org/apache/struts2/action/SessionAware.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,30 +16,25 @@ * specific language governing permissions and limitations * under the License. */ - -package org.apache.struts2.interceptor; +package org.apache.struts2.action; import java.util.Map; - /** - *

    * Actions that want access to the user's HTTP session attributes should implement this interface. - *

    - *

    + * * This will give them access to a Map where they can put objects that can be made available * to subsequent requests. - *

    - *

    + * * Typical uses may be cached user data such as name, or a shopping cart. - *

    */ public interface SessionAware { /** - * Sets the Map of session attributes in the implementing class. + * Applies the Map of session attributes in the implementing class. * * @param session a Map of HTTP session attribute name/value pairs. */ - public void setSession(Map session); + void withSession(Map session); + } diff --git a/core/src/main/java/org/apache/struts2/action/UploadedFilesAware.java b/core/src/main/java/org/apache/struts2/action/UploadedFilesAware.java new file mode 100644 index 0000000000..92ec9c98b8 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/action/UploadedFilesAware.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.struts2.action; + +import org.apache.struts2.dispatcher.multipart.UploadedFile; + +import java.util.List; + +/** + * Actions that want to be aware of all the uploaded file should implement this interface. + * The {@link org.apache.struts2.interceptor.ActionFileUploadInterceptor} will use the interface + * to notify action about the multiple uploaded files. + */ +public interface UploadedFilesAware { + + /** + * Notifies action about the multiple uploaded files, when a single file is uploaded + * the list will have just one element + * + * @param uploadedFiles a list of {@link UploadedFile}, cannot be null. It can be empty. + */ + void withUploadedFiles(List uploadedFiles); + +} diff --git a/core/src/main/java/org/apache/struts2/components/ActionComponent.java b/core/src/main/java/org/apache/struts2/components/ActionComponent.java index d6fb690c89..b1260cc8b7 100644 --- a/core/src/main/java/org/apache/struts2/components/ActionComponent.java +++ b/core/src/main/java/org/apache/struts2/components/ActionComponent.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,36 +16,32 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.ActionProxy; -import com.opensymphony.xwork2.ActionProxyFactory; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.util.ValueStackFactory; +import org.apache.struts2.ActionContext; +import org.apache.struts2.ActionInvocation; +import org.apache.struts2.ActionProxy; +import org.apache.struts2.ActionProxyFactory; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; +import org.apache.struts2.util.ValueStackFactory; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.jsp.PageContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.ServletActionContext; import org.apache.struts2.StrutsException; import org.apache.struts2.StrutsStatics; import org.apache.struts2.dispatcher.Dispatcher; -import org.apache.struts2.dispatcher.RequestMap; import org.apache.struts2.dispatcher.HttpParameters; -import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.dispatcher.RequestMap; import org.apache.struts2.dispatcher.mapper.ActionMapping; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import org.apache.struts2.views.jsp.TagUtils; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.jsp.PageContext; import java.io.IOException; import java.io.Writer; -import java.util.HashMap; import java.util.Map; /** @@ -56,7 +50,7 @@ * namespace. The body content of the tag is used to render the results from the Action. Any result processor defined * for this action in struts.xml will be ignored, unless the executeResult parameter is specified.

    * - * + *

    * *

      *
    • id (String) - the id (if specified) to put the action under stack's context. @@ -114,9 +108,8 @@ * <s:property value="#attr.stringByAction" /> * * - * */ -@StrutsTag(name="action", tldTagClass="org.apache.struts2.views.jsp.ActionTag", description="Execute an action from within a view") +@StrutsTag(name = "action", tldTagClass = "org.apache.struts2.views.jsp.ActionTag", description = "Execute an action from within a view") public class ActionComponent extends ContextBean { private static final Logger LOG = LogManager.getLogger(ActionComponent.class); @@ -146,17 +139,13 @@ public ActionComponent(ValueStack stack, HttpServletRequest req, HttpServletResp public void setActionProxyFactory(ActionProxyFactory actionProxyFactory) { this.actionProxyFactory = actionProxyFactory; } - + @Inject public void setValueStackFactory(ValueStackFactory valueStackFactory) { this.valueStackFactory = valueStackFactory; } - @Inject - public void setActionMapper(ActionMapper mapper) { - this.actionMapper = mapper; - } - + @Override public boolean end(Writer writer, String body) { boolean end = super.end(writer, "", false); try { @@ -164,7 +153,7 @@ public boolean end(Writer writer, String body) { try { writer.flush(); } catch (IOException e) { - LOG.warn("error while trying to flush writer ", e); + LOG.warn("error while trying to flush writer ", e); } } executeAction(); @@ -178,62 +167,49 @@ public boolean end(Writer writer, String body) { return end; } - protected Map createExtraContext() { + protected Map createExtraContext() { HttpParameters newParams = createParametersForContext(); - ActionContext ctx = new ActionContext(stack.getContext()); - PageContext pageContext = (PageContext) ctx.get(ServletActionContext.PAGE_CONTEXT); - Map session = ctx.getSession(); - Map application = ctx.getApplication(); + ActionContext ctx = stack.getActionContext(); + PageContext pageContext = ctx.getPageContext(); + Map session = ctx.getSession(); + Map application = ctx.getApplication(); Dispatcher du = Dispatcher.getInstance(); - Map extraContext = du.createContextMap(new RequestMap(req), - newParams, - session, - application, - req, - res); + Map extraContext = du.createContextMap( + new RequestMap(req), + newParams, + session, + application, + req, + res); ValueStack newStack = valueStackFactory.createValueStack(stack); - extraContext.put(ActionContext.VALUE_STACK, newStack); - // add page context, such that ServletDispatcherResult will do an include - extraContext.put(ServletActionContext.PAGE_CONTEXT, pageContext); - - return extraContext; + return ActionContext.of(extraContext) + .withValueStack(newStack) + // add page context, such that ServletDispatcherResult will do an include + .withPageContext(pageContext) + .getContextMap(); } /** - * Creates parameters map using parameters from the value stack and component parameters. Any non-String array - * values will be converted into a single-value String array. - * - * @return A map of String[] parameters + * Creates {@link HttpParameters} using parameters from the value stack and component attributes. + * Any non-String array values will be converted into a single-value String array. + * + * @return Instance of {@link HttpParameters} */ protected HttpParameters createParametersForContext() { HttpParameters parentParams = null; if (!ignoreContextParams) { - parentParams = new ActionContext(getStack().getContext()).getParameters(); + parentParams = getStack().getActionContext().getParameters(); } - HttpParameters.Builder builder = HttpParameters.create(); - if (parentParams != null) { - builder = builder.withParent(parentParams); - } + HttpParameters.Builder builder = HttpParameters.create().withParent(parentParams); - if (parameters != null) { - Map params = new HashMap<>(); - for (Object o : parameters.entrySet()) { - Map.Entry entry = (Map.Entry) o; - String key = (String) entry.getKey(); - Object val = entry.getValue(); - if (val.getClass().isArray() && String.class == val.getClass().getComponentType()) { - params.put(key, (String[])val); - } else { - params.put(key, new String[]{val.toString()}); - } - } - builder = builder.withExtraParams(params); + if (attributes != null) { + builder = builder.withExtraParams(attributes); } return builder.build(); } @@ -247,8 +223,6 @@ public ActionProxy getProxy() { * attempt to derive a namespace using buildNamespace(). The ActionProxy * and the namespace will be saved into the instance variables proxy and * namespace respectively. - * - * @see org.apache.struts2.views.jsp.TagUtils#buildNamespace */ protected void executeAction() { String actualName = findString(name, "name", "Action name is required. Example: updatePerson"); @@ -268,7 +242,7 @@ protected void executeAction() { String namespace; if (this.namespace == null) { - namespace = TagUtils.buildNamespace(actionMapper, getStack(), req); + namespace = getNamespace(getStack()); } else { namespace = findString(this.namespace); } @@ -296,7 +270,7 @@ protected void executeAction() { // set the old stack back on the request req.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack); if (inv != null) { - ActionContext.getContext().setActionInvocation(inv); + ActionContext.getContext().withActionInvocation(inv); } } @@ -305,32 +279,32 @@ protected void executeAction() { } } - @StrutsTagAttribute(required=true,description="Name of the action to be executed (without the extension suffix eg. .action)") + @StrutsTagAttribute(required = true, description = "Name of the action to be executed (without the extension suffix eg. .action)") public void setName(String name) { this.name = name; } - @StrutsTagAttribute(description="Namespace for action to call", defaultValue="namespace from where tag is used") + @StrutsTagAttribute(description = "Namespace for action to call", defaultValue = "namespace from where tag is used") public void setNamespace(String namespace) { this.namespace = namespace; } - @StrutsTagAttribute(description="Whether the result of this action (probably a view) should be executed/rendered", type="Boolean", defaultValue="false") + @StrutsTagAttribute(description = "Whether the result of this action (probably a view) should be executed/rendered", type = "Boolean", defaultValue = "false") public void setExecuteResult(boolean executeResult) { this.executeResult = executeResult; } - @StrutsTagAttribute(description="Whether the request parameters are to be included when the action is invoked", type="Boolean", defaultValue="false") + @StrutsTagAttribute(description = "Whether the request parameters are to be included when the action is invoked", type = "Boolean", defaultValue = "false") public void setIgnoreContextParams(boolean ignoreContextParams) { this.ignoreContextParams = ignoreContextParams; } - @StrutsTagAttribute(description="Whether the writer should be flush upon end of action component tag, default to true", type="Boolean", defaultValue="true") + @StrutsTagAttribute(description = "Whether the writer should be flush upon end of action component tag, default to true", type = "Boolean", defaultValue = "true") public void setFlush(boolean flush) { this.flush = flush; } - @StrutsTagAttribute(description="Whether an exception should be rethrown, if the target action throws an exception", type="Boolean", defaultValue="false") + @StrutsTagAttribute(description = "Whether an exception should be rethrown, if the target action throws an exception", type = "Boolean", defaultValue = "false") public void setRethrowException(boolean rethrowException) { this.rethrowException = rethrowException; } diff --git a/core/src/main/java/org/apache/struts2/components/ActionError.java b/core/src/main/java/org/apache/struts2/components/ActionError.java index 4ce34a3af0..d006aa34ba 100644 --- a/core/src/main/java/org/apache/struts2/components/ActionError.java +++ b/core/src/main/java/org/apache/struts2/components/ActionError.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.commons.lang3.StringUtils; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.util.Collection; import java.util.List; @@ -64,10 +61,12 @@ public ActionError(ValueStack stack, HttpServletRequest request, HttpServletResp super(stack, request, response); } + @Override protected String getDefaultTemplate() { return TEMPLATE; } + @Override protected void evaluateExtraParams() { boolean isEmptyList = true; Collection actionMessages = (List) findValue("actionErrors"); diff --git a/core/src/main/java/org/apache/struts2/components/ActionMessage.java b/core/src/main/java/org/apache/struts2/components/ActionMessage.java index c62dd5db91..8c68f5ba62 100644 --- a/core/src/main/java/org/apache/struts2/components/ActionMessage.java +++ b/core/src/main/java/org/apache/struts2/components/ActionMessage.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.commons.lang3.StringUtils; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.util.Collection; import java.util.List; @@ -62,10 +59,12 @@ public ActionMessage(ValueStack stack, HttpServletRequest request, HttpServletRe super(stack, request, response); } + @Override protected String getDefaultTemplate() { return TEMPLATE; } + @Override protected void evaluateExtraParams() { boolean isEmptyList = true; Collection actionMessages = (List) findValue("actionMessages"); diff --git a/core/src/main/java/org/apache/struts2/components/Anchor.java b/core/src/main/java/org/apache/struts2/components/Anchor.java index 118ae6f021..6bda43f209 100644 --- a/core/src/main/java/org/apache/struts2/components/Anchor.java +++ b/core/src/main/java/org/apache/struts2/components/Anchor.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,11 +16,12 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -30,8 +29,6 @@ import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.StringWriter; import java.io.Writer; import java.util.LinkedHashMap; @@ -72,9 +69,9 @@ public class Anchor extends ClosingUIBean { protected UrlProvider urlProvider; protected UrlRenderer urlRenderer; protected boolean processingTagBody = false; - + //these params are passed by the Param tag - protected Map urlParameters = new LinkedHashMap(); + protected Map urlParameters = new LinkedHashMap<>(); public Anchor(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { super(stack, request, response); @@ -83,14 +80,17 @@ public Anchor(ValueStack stack, HttpServletRequest request, HttpServletResponse urlProvider.setHttpServletResponse(response); } + @Override public String getDefaultOpenTemplate() { return OPEN_TEMPLATE; } + @Override protected String getDefaultTemplate() { return TEMPLATE; } + @Override public boolean usesBody() { return true; } @@ -99,17 +99,20 @@ public boolean usesBody() { protected void evaluateExtraParams() { super.evaluateExtraParams(); - if (href != null) + if (href != null) { addParameter("href", ensureAttributeSafelyNotEscaped(findString(href))); - else { + } else { //no href, build it from URL attributes StringWriter sw = new StringWriter(); urlRenderer.beforeRenderUrl(urlProvider); urlRenderer.renderUrl(sw, urlProvider); String builtHref = sw.toString(); - if (StringUtils.isNotEmpty(builtHref)) + if (StringUtils.isNotEmpty(builtHref)) { addParameter("href", ensureAttributeSafelyNotEscaped(builtHref)); + } } + + addParameter("escapeHtmlBody", escapeHtmlBody); } @Inject(StrutsConstants.STRUTS_URL_INCLUDEPARAMS) @@ -118,10 +121,10 @@ public void setUrlIncludeParams(String urlIncludeParams) { } @Inject - public void setUrlRenderer(UrlRenderer urlRenderer) { - urlProvider.setUrlRenderer(urlRenderer); + public void setUrlRenderer(UrlRenderer urlRenderer) { + urlProvider.setUrlRenderer(urlRenderer); this.urlRenderer = urlRenderer; - } + } @Inject(required=false) public void setExtraParameterProvider(ExtraParameterProvider provider) { @@ -138,6 +141,7 @@ public boolean start(Writer writer) { /** * Overrides to be able to render body in a template rather than always before the template */ + @Override public boolean end(Writer writer, String body) { this.processingTagBody = false; evaluateParams(); @@ -146,15 +150,14 @@ public boolean end(Writer writer, String body) { mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate())); } catch (Exception e) { LOG.error("error when rendering", e); - } - finally { + } finally { popComponentStack(); } return false; } - + @Override public void addParameter(String key, Object value) { /* the parameters added by this method are used in the template. this method is also @@ -163,21 +166,23 @@ public void addParameter(String key, Object value) { */ if (processingTagBody) { this.urlParameters.put(key, value); - } else + } else { super.addParameter(key, value); + } } @Override - public void addAllParameters(Map params) { + public void addAllAttributes(Map additionalAttributes) { /* - the parameters added by this method are used in the template. this method is also - called by Param to add params into ancestestor. This tag needs to keep both set of parameters + The attributes added by this method are used in the template. This method is also + called by Param to add attributes into an ancestor. This tag needs to keep both set of parameters separated (You gotta keep 'em separated!) */ if (processingTagBody) { - this.urlParameters.putAll(params); - } else - super.addAllParameters(params); + this.urlParameters.putAll(additionalAttributes); + } else { + super.addAllAttributes(additionalAttributes); + } } public UrlProvider getUrlProvider() { @@ -199,6 +204,7 @@ public void setScheme(String scheme) { urlProvider.setScheme(scheme); } + @Override @StrutsTagAttribute(description = "The target value to use, if not using action") public void setValue(String value) { urlProvider.setValue(value); @@ -258,4 +264,9 @@ public void setEscapeAmp(boolean escapeAmp) { public void setForceAddSchemeHostAndPort(boolean forceAddSchemeHostAndPort) { urlProvider.setForceAddSchemeHostAndPort(forceAddSchemeHostAndPort); } + + @StrutsTagAttribute(description = "Specifies whether to HTML-escape the tag body or not", type = "Boolean", defaultValue = "false") + public void setEscapeHtmlBody(boolean escapeHtmlBody) { + this.escapeHtmlBody = escapeHtmlBody; + } } diff --git a/core/src/main/java/org/apache/struts2/components/AppendIterator.java b/core/src/main/java/org/apache/struts2/components/AppendIterator.java index c639b08aa1..b57d274095 100644 --- a/core/src/main/java/org/apache/struts2/components/AppendIterator.java +++ b/core/src/main/java/org/apache/struts2/components/AppendIterator.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.components.Param.UnnamedParametric; @@ -32,7 +29,6 @@ import java.io.Writer; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; /** @@ -56,49 +52,49 @@ *
    • Third Entry of the Third ITerator
    • * * - * + *

      * *

        *
      • var (String) - the name of which if supplied will have the resultant * appended iterator stored under in the stack's context
      • *
      * - * - * + *

      + *

      * * public class AppendIteratorTagAction extends ActionSupport { - * + *

      * private List myList1; * private List myList2; * private List myList3; - * - * + *

      + *

      * public String execute() throws Exception { - * + *

      * myList1 = new ArrayList(); * myList1.add("1"); * myList1.add("2"); * myList1.add("3"); - * + *

      * myList2 = new ArrayList(); * myList2.add("a"); * myList2.add("b"); * myList2.add("c"); - * + *

      * myList3 = new ArrayList(); * myList3.add("A"); * myList3.add("B"); * myList3.add("C"); - * + *

      * return "done"; * } - * + *

      * public List getMyList1() { return myList1; } * public List getMyList2() { return myList2; } * public List getMyList3() { return myList3; } - *} + * } * - * + *

      * * <s:append var="myAppendIterator"> * <s:param value="%{myList1}" /> @@ -110,36 +106,33 @@ * </s:iterator> * * - * * @see org.apache.struts2.util.AppendIteratorFilter * @see org.apache.struts2.views.jsp.iterator.AppendIteratorTag - * */ -@StrutsTag(name="append", tldTagClass="org.apache.struts2.views.jsp.iterator.AppendIteratorTag", description="Append the values of a list of iterators to one iterator") +@StrutsTag(name = "append", tldTagClass = "org.apache.struts2.views.jsp.iterator.AppendIteratorTag", description = "Append the values of a list of iterators to one iterator") public class AppendIterator extends ContextBean implements UnnamedParametric { private static final Logger LOG = LogManager.getLogger(AppendIterator.class); - private AppendIteratorFilter appendIteratorFilter= null; - private List _parameters; + private AppendIteratorFilter appendIteratorFilter = null; + private List attributesToAppend; public AppendIterator(ValueStack stack) { super(stack); } + @Override public boolean start(Writer writer) { - _parameters = new ArrayList(); + attributesToAppend = new ArrayList<>(); appendIteratorFilter = new AppendIteratorFilter(); return super.start(writer); } + @Override public boolean end(Writer writer, String body) { - - for (Iterator paramEntries = _parameters.iterator(); paramEntries.hasNext(); ) { - - Object iteratorEntryObj = paramEntries.next(); - if (! MakeIterator.isIterable(iteratorEntryObj)) { + for (Object iteratorEntryObj : attributesToAppend) { + if (!MakeIterator.isIterable(iteratorEntryObj)) { LOG.warn("param with value resolved as {} cannot be make as iterator, it will be ignored and hence will not appear in the merged iterator", iteratorEntryObj); continue; } @@ -156,11 +149,13 @@ public boolean end(Writer writer, String body) { } // UnnamedParametric implementation -------------------------------------- + @Override public void addParameter(Object value) { - _parameters.add(value); + attributesToAppend.add(value); } - @StrutsTagAttribute(description="The name of which if supplied will have the resultant appended iterator stored under in the stack's context") + @StrutsTagAttribute(description = "The name of which if supplied will have the resultant appended iterator stored under in the stack's context") + @Override public void setVar(String var) { super.setVar(var); } diff --git a/core/src/main/java/org/apache/struts2/components/Bean.java b/core/src/main/java/org/apache/struts2/components/Bean.java index d01e63b293..db39cb16f5 100644 --- a/core/src/main/java/org/apache/struts2/components/Bean.java +++ b/core/src/main/java/org/apache/struts2/components/Bean.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,15 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.ObjectFactory; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; +import org.apache.struts2.util.reflection.ReflectionProvider; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; diff --git a/core/src/main/java/org/apache/struts2/components/Checkbox.java b/core/src/main/java/org/apache/struts2/components/Checkbox.java index a9f0fdc6b6..87c400d018 100644 --- a/core/src/main/java/org/apache/struts2/components/Checkbox.java +++ b/core/src/main/java/org/apache/struts2/components/Checkbox.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,16 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; +import org.apache.struts2.StrutsConstants; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import com.opensymphony.xwork2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** * @@ -49,17 +47,22 @@ * * * - * */ @StrutsTag( - name="checkbox", - tldTagClass="org.apache.struts2.views.jsp.ui.CheckboxTag", - description="Render a checkbox input field", - allowDynamicAttributes=true) + name = "checkbox", + tldTagClass = "org.apache.struts2.views.jsp.ui.CheckboxTag", + description = "Render a checkbox input field", + allowDynamicAttributes = true) public class Checkbox extends UIBean { - final public static String TEMPLATE = "checkbox"; + + private static final String ATTR_SUBMIT_UNCHECKED = "submitUnchecked"; + + public static final String TEMPLATE = "checkbox"; + + private String submitUncheckedGlobal; protected String fieldValue; + protected String submitUnchecked; public Checkbox(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { super(stack, request, response); @@ -71,19 +74,47 @@ protected String getDefaultTemplate() { protected void evaluateExtraParams() { if (fieldValue != null) { - addParameter("fieldValue", findString(fieldValue)); + addParameter(ATTR_FIELD_VALUE, findString(fieldValue)); + } else { + addParameter(ATTR_FIELD_VALUE, "true"); + } + + if (submitUnchecked != null) { + Object parsedValue = findValue(submitUnchecked, Boolean.class); + addParameter(ATTR_SUBMIT_UNCHECKED, parsedValue == null ? Boolean.valueOf(submitUnchecked) : parsedValue); + } else if (submitUncheckedGlobal != null) { + addParameter(ATTR_SUBMIT_UNCHECKED, Boolean.parseBoolean(submitUncheckedGlobal)); } else { - addParameter("fieldValue", "true"); + addParameter(ATTR_SUBMIT_UNCHECKED, false); } } - protected Class getValueClassType() { + @Override + protected Class getValueClassType() { return Boolean.class; // for checkboxes, everything needs to end up as a Boolean } - @StrutsTagAttribute(description="The actual HTML value attribute of the checkbox.", defaultValue="true") + @Inject(value = StrutsConstants.STRUTS_UI_CHECKBOX_SUBMIT_UNCHECKED, required = false) + public void setSubmitUncheckedGlobal(String submitUncheckedGlobal) { + this.submitUncheckedGlobal = submitUncheckedGlobal; + } + + @StrutsTagAttribute(description = "The actual HTML value attribute of the checkbox.", defaultValue = "true") public void setFieldValue(String fieldValue) { this.fieldValue = fieldValue; } + @StrutsTagAttribute(description = "If set to true, unchecked elements will be submitted with the form. " + + "Since Struts 6.1.1 you can use a constant \"" + StrutsConstants.STRUTS_UI_CHECKBOX_SUBMIT_UNCHECKED + "\" to set this attribute globally", + type = "Boolean", defaultValue = "false") + public void setSubmitUnchecked(String submitUnchecked) { + this.submitUnchecked = submitUnchecked; + } + + @Override + @StrutsTagAttribute(description = "Define label position of form element (top/left), also 'right' is supported when using 'xhtml' theme") + public void setLabelPosition(String labelPosition) { + super.setLabelPosition(labelPosition); + } + } diff --git a/core/src/main/java/org/apache/struts2/components/CheckboxList.java b/core/src/main/java/org/apache/struts2/components/CheckboxList.java index fde4037897..acf8b44053 100644 --- a/core/src/main/java/org/apache/struts2/components/CheckboxList.java +++ b/core/src/main/java/org/apache/struts2/components/CheckboxList.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.views.annotations.StrutsTag; -import org.apache.struts2.views.annotations.StrutsTagAttribute; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; /** * @@ -52,7 +48,7 @@ allowDynamicAttributes = true) public class CheckboxList extends ListUIBean { final public static String TEMPLATE = "checkboxlist"; - + public CheckboxList(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { super(stack, request, response); } @@ -60,9 +56,19 @@ public CheckboxList(ValueStack stack, HttpServletRequest request, HttpServletRes protected String getDefaultTemplate() { return TEMPLATE; } - + public void evaluateExtraParams() { super.evaluateExtraParams(); } -} \ No newline at end of file + /** + * Checkboxlist tag requires lazy evaluation as list of tags is dynamically generated using + * + * @return boolean true by default + */ + @Override + protected boolean lazyEvaluation() { + return true; + } + +} diff --git a/core/src/main/java/org/apache/struts2/components/ClosingUIBean.java b/core/src/main/java/org/apache/struts2/components/ClosingUIBean.java index 123d58bc79..89d6444c25 100644 --- a/core/src/main/java/org/apache/struts2/components/ClosingUIBean.java +++ b/core/src/main/java/org/apache/struts2/components/ClosingUIBean.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.Writer; /** @@ -49,6 +46,7 @@ public void setOpenTemplate(String openTemplate) { this.openTemplate = openTemplate; } + @Override public boolean start(Writer writer) { boolean result = super.start(writer); try { diff --git a/core/src/main/java/org/apache/struts2/components/ComboBox.java b/core/src/main/java/org/apache/struts2/components/ComboBox.java index e2f98b6dec..2ae6dfd34a 100644 --- a/core/src/main/java/org/apache/struts2/components/ComboBox.java +++ b/core/src/main/java/org/apache/struts2/components/ComboBox.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.util.MakeIterator; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.util.Collection; import java.util.Iterator; import java.util.Map; @@ -129,8 +126,7 @@ public void evaluateExtraParams() { } if (value != null) { - if (value instanceof Collection) { - Collection tmp = (Collection) value; + if (value instanceof Collection tmp) { addParameter("list", tmp); if (listKey != null) { addParameter("listKey", listKey); @@ -138,11 +134,10 @@ public void evaluateExtraParams() { if (listValue != null) { addParameter("listValue", listValue); } - } else if (value instanceof Map) { - Map tmp = (Map) value; + } else if (value instanceof Map tmp) { addParameter("list", MakeIterator.convert(tmp)); addParameter("listKey", "key"); - addParameter("listValue", "value"); + addParameter("listValue", "value"); } else { // also covers "if (value.getClass().isArray())" Iterator i = MakeIterator.convert(value); addParameter("list", i); diff --git a/core/src/main/java/org/apache/struts2/components/Component.java b/core/src/main/java/org/apache/struts2/components/Component.java index 2505fd2ddb..c9cd1bd675 100644 --- a/core/src/main/java/org/apache/struts2/components/Component.java +++ b/core/src/main/java/org/apache/struts2/components/Component.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,15 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.AnnotationUtils; -import com.opensymphony.xwork2.util.TextParseUtil; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.ActionContext; +import org.apache.struts2.ActionInvocation; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.security.NotExcludedAcceptedPatternsChecker; +import org.apache.struts2.util.TextParseUtil; +import org.apache.struts2.util.ValueStack; import org.apache.commons.lang3.BooleanUtils; import org.apache.commons.lang3.StringUtils; +import org.apache.commons.lang3.reflect.MethodUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.StrutsConstants; @@ -36,16 +36,19 @@ import org.apache.struts2.util.ComponentUtils; import org.apache.struts2.util.FastByteArrayOutputStream; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import org.apache.struts2.views.jsp.TagUtils; import org.apache.struts2.views.util.UrlHelper; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.PrintWriter; import java.io.Writer; import java.lang.reflect.Method; -import java.util.*; +import java.util.Collection; +import java.util.HashSet; +import java.util.LinkedHashMap; +import java.util.Map; +import java.util.Stack; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; @@ -53,7 +56,6 @@ * Base class to extend for UI components. *
      * This class is a good extension point when building reusable UI components. - * */ public class Component { @@ -67,29 +69,34 @@ public class Component { protected static ConcurrentMap, Collection> standardAttributesMap = new ConcurrentHashMap<>(); protected boolean devMode = false; + protected boolean escapeHtmlBody = false; protected ValueStack stack; - protected Map parameters; + protected Map attributes; protected ActionMapper actionMapper; protected boolean throwExceptionOnELFailure; + protected boolean performClearTagStateForTagPoolingServers = false; private UrlHelper urlHelper; + private NotExcludedAcceptedPatternsChecker notExcludedAcceptedPatterns; + /** * Constructor. * - * @param stack OGNL value stack. + * @param stack OGNL value stack. */ public Component(ValueStack stack) { this.stack = stack; - this.parameters = new LinkedHashMap<>(); + this.attributes = new LinkedHashMap<>(); getComponentStack().push(this); } /** * Gets the name of this component. + * * @return the name of this component. */ private String getComponentName() { - Class c = getClass(); + Class c = getClass(); String name = c.getName(); int dot = name.lastIndexOf('.'); @@ -111,12 +118,24 @@ public void setThrowExceptionsOnELFailure(String throwException) { this.throwExceptionOnELFailure = BooleanUtils.toBoolean(throwException); } + @Inject(value = StrutsConstants.STRUTS_UI_ESCAPE_HTML_BODY, required = false) + public void setEscapeHtmlBody(String escapeHtmlBody) { + this.escapeHtmlBody = BooleanUtils.toBoolean(escapeHtmlBody); + } + @Inject public void setUrlHelper(UrlHelper urlHelper) { this.urlHelper = urlHelper; } + + @Inject + public void setNotExcludedAcceptedPatterns(NotExcludedAcceptedPatternsChecker notExcludedAcceptedPatterns) { + this.notExcludedAcceptedPatterns = notExcludedAcceptedPatterns; + } + /** * Gets the OGNL value stack associated with this component. + * * @return the OGNL value stack associated with this component. */ public ValueStack getStack() { @@ -125,6 +144,7 @@ public ValueStack getStack() { /** * Gets the component stack of this component. + * * @return the component stack of this component, never null. */ public Stack getComponentStack() { @@ -140,7 +160,7 @@ public Stack getComponentStack() { * Callback for the start tag of this component. * Should the body be evaluated? * - * @param writer the output writer. + * @param writer the output writer. * @return true if the body should be evaluated */ public boolean start(Writer writer) { @@ -152,8 +172,9 @@ public boolean start(Writer writer) { * Should the body be evaluated again? *
      * NOTE: will pop component stack. - * @param writer the output writer. - * @param body the rendered body. + * + * @param writer the output writer. + * @param body the rendered body. * @return true if the body should be evaluated again */ public boolean end(Writer writer, String body) { @@ -165,13 +186,14 @@ public boolean end(Writer writer, String body) { * Should the body be evaluated again? *
      * NOTE: has a parameter to determine to pop the component stack. - * @param writer the output writer. - * @param body the rendered body. - * @param popComponentStack should the component stack be popped? + * + * @param writer the output writer. + * @param body the rendered body. + * @param popComponentStack should the component stack be popped? * @return true if the body should be evaluated again */ protected boolean end(Writer writer, String body, boolean popComponentStack) { - assert(body != null); + assert (body != null); try { writer.write(body); @@ -193,18 +215,18 @@ protected void popComponentStack() { /** * Finds the nearest ancestor of this component stack. + * * @param clazz the class to look for, or if assignable from. - * @return the component if found, null if not. + * @return the component if found, null if not. */ - protected Component findAncestor(Class clazz) { - Stack componentStack = getComponentStack(); + protected Component findAncestor(Class clazz) { + Stack componentStack = getComponentStack(); int currPosition = componentStack.search(this); if (currPosition >= 0) { int start = componentStack.size() - currPosition - 1; - //for (int i = componentStack.size() - 2; i >= 0; i--) { - for (int i = start; i >=0; i--) { - Component component = (Component) componentStack.get(i); + for (int i = start; i >= 0; i--) { + Component component = componentStack.get(i); if (clazz.isAssignableFrom(component.getClass()) && component != this) { return component; } @@ -216,8 +238,9 @@ protected Component findAncestor(Class clazz) { /** * Evaluates the OGNL stack to find a String value. - * @param expr OGNL expression. - * @return the String value found. + * + * @param expr OGNL expression. + * @return the String value found. */ protected String findString(String expr) { return (String) findValue(expr, String.class); @@ -229,10 +252,10 @@ protected String findString(String expr) { * If the given expression is null a error is logged and a RuntimeException is thrown * constructed with a messaged based on the given field and errorMsg parameter. * - * @param expr OGNL expression. - * @param field field name used when throwing RuntimeException. - * @param errorMsg error message used when throwing RuntimeException. - * @return the String value found. + * @param expr OGNL expression. + * @param field field name used when throwing RuntimeException. + * @param errorMsg error message used when throwing RuntimeException. + * @return the String value found. * @throws StrutsException is thrown in case of expression is null. */ protected String findString(String expr, String field, String errorMsg) { @@ -248,79 +271,63 @@ protected String findString(String expr, String field, String errorMsg) { *
      * A message is constructed and logged at ERROR level before being returned * as a RuntimeException. - * @param field field name used when throwing RuntimeException. - * @param errorMsg error message used when throwing RuntimeException. - * @param e the caused exception, can be null. - * @return the constructed StrutsException. + * + * @param field field name used when throwing RuntimeException. + * @param errorMsg error message used when throwing RuntimeException. + * @param e the caused exception, can be null. + * @return the constructed StrutsException. */ protected StrutsException fieldError(String field, String errorMsg, Exception e) { String msg = "tag '" + getComponentName() + "', field '" + field + - ( parameters != null && parameters.containsKey("name")?"', name '" + parameters.get("name"):"") + - "': " + errorMsg; + (attributes != null && attributes.containsKey("name") ? "', name '" + attributes.get("name") : "") + + "': " + errorMsg; throw new StrutsException(msg, e); } /** * Finds a value from the OGNL stack based on the given expression. * Will always evaluate expr against stack except when expr - * is null. If altsyntax (%{...}) is applied, simply strip it off. + * is null. If %{...} is applied, simply strip it off. * - * @param expr the expression. Returns null if expr is null. + * @param expression the expression. Returns null if expr is null. * @return the value, null if not found. */ - protected Object findValue(String expr) { - if (expr == null) { + protected Object findValue(String expression) { + if (expression == null) { return null; } - expr = stripExpressionIfAltSyntax(expr); + expression = stripExpression(expression); - return getStack().findValue(expr, throwExceptionOnELFailure); + return getStack().findValue(expression, throwExceptionOnELFailure); } /** - * If altsyntax (%{...}) is applied, simply strip the "%{" and "}" off. - * @param expr the expression (must be not null) - * @return the stripped expression if altSyntax is enabled. Otherwise - * the parameter expression is returned as is. - */ - protected String stripExpressionIfAltSyntax(String expr) { - return ComponentUtils.stripExpressionIfAltSyntax(stack, expr); - } - - /** - * See struts.properties where the altSyntax flag is defined. - * @return if the altSyntax enabled? [TRUE] + * If %{...} is applied, simply strip the "%{" and "}" off. + * + * @param expression the expression (must be not null) + * @return the stripped expression */ - public boolean altSyntax() { - return ComponentUtils.altSyntax(stack); + protected String stripExpression(String expression) { + return ComponentUtils.stripExpression(expression); } /** * Adds the surrounding %{ } to the expression for proper processing. + * * @param expr the expression. - * @return the modified expression if altSyntax is enabled, or the parameter - * expression otherwise. - */ - protected String completeExpressionIfAltSyntax(String expr) { - if (altSyntax()) { - return "%{" + expr + "}"; - } - return expr; - } - - /** - * This check is needed for backwards compatibility with 2.1.x - * @param expr the expression. - * @return the found string if altSyntax is enabled. The parameter - * expression otherwise. + * @return the modified expression wrapped with %{...} */ - protected String findStringIfAltSyntax(String expr) { - if (altSyntax()) { - return findString(expr); - } - return expr; - } + protected String completeExpression(String expr) { + if (expr == null) { + return null; + } + if (ComponentUtils.isExpression(expr)) { + LOG.warn("Expression {} is already an expression!", expr); + return expr; + } + return "%{" + expr + "}"; + } /** *

      @@ -334,10 +341,10 @@ protected String findStringIfAltSyntax(String expr) { * messaged based on the given field and errorMsg parameter. *

      * - * @param expr OGNL expression. - * @param field field name used when throwing RuntimeException. - * @param errorMsg error message used when throwing RuntimeException. - * @return the Object found, is never null. + * @param expr OGNL expression. + * @param field field name used when throwing RuntimeException. + * @param errorMsg error message used when throwing RuntimeException. + * @return the Object found, is never null. * @throws StrutsException is thrown in case of not found in the OGNL stack, or expression is null. */ protected Object findValue(String expr, String field, String errorMsg) { @@ -362,46 +369,45 @@ protected Object findValue(String expr, String field, String errorMsg) { /** * Evaluates the OGNL stack to find an Object of the given type. Will evaluate - * expr the portion wrapped with altSyntax (%{...}) - * against stack when altSyntax is on, else the whole expr - * is evaluated against the stack. - *
      - * This method only supports the altSyntax. So this should be set to true. - * @param expr OGNL expression. - * @param toType the type expected to find. - * @return the Object found, or null if not found. + * expression the portion wrapped with %{...} against stack if + * evaluating to String.class, else the whole expression is evaluated + * against the stack. + * + * @param expression OGNL expression. + * @param toType the type expected to find. + * @return the Object found, or null if not found. */ - protected Object findValue(String expr, Class toType) { - if (altSyntax() && toType == String.class) { - if (ComponentUtils.containsExpression(expr)) { - return TextParseUtil.translateVariables('%', expr, stack); + protected Object findValue(String expression, Class toType) { + if (toType == String.class) { + if (ComponentUtils.containsExpression(expression)) { + return TextParseUtil.translateVariables('%', expression, stack); } else { - return expr; + return expression; } } else { - expr = stripExpressionIfAltSyntax(expr); - - return getStack().findValue(expr, toType, throwExceptionOnELFailure); + String strippedExpression = stripExpression(expression); + return getStack().findValue(strippedExpression, toType, throwExceptionOnELFailure); } } /** * Renders an action URL by consulting the {@link org.apache.struts2.dispatcher.mapper.ActionMapper}. - * @param action the action - * @param namespace the namespace - * @param method the method - * @param req HTTP request - * @param res HTTP response - * @param parameters parameters - * @param scheme http or https - * @param includeContext should the context path be included or not - * @param encodeResult should the url be encoded - * @param forceAddSchemeHostAndPort should the scheme host and port be forced - * @param escapeAmp should ampersand (&) be escaped to &amp; + * + * @param action the action + * @param namespace the namespace + * @param method the method + * @param req HTTP request + * @param res HTTP response + * @param parameters parameters + * @param scheme http or https + * @param includeContext should the context path be included or not + * @param encodeResult should the url be encoded + * @param forceAddSchemeHostAndPort should the scheme host and port be forced + * @param escapeAmp should ampersand (&) be escaped to &amp; * @return the action url. */ protected String determineActionURL(String action, String namespace, String method, - HttpServletRequest req, HttpServletResponse res, Map parameters, String scheme, + HttpServletRequest req, HttpServletResponse res, Map parameters, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, boolean escapeAmp) { String finalAction = findString(action); @@ -414,16 +420,17 @@ protected String determineActionURL(String action, String namespace, String meth /** * Determines the namespace of the current page being renderdd. Useful for Form, URL, and href generations. - * @param namespace the namespace - * @param stack OGNL value stack - * @param req HTTP request - * @return the namepsace of the current page being rendered, is never null. + * + * @param namespace the namespace + * @param stack OGNL value stack + * @param req HTTP request + * @return the namepsace of the current page being rendered, is never null. */ protected String determineNamespace(String namespace, ValueStack stack, HttpServletRequest req) { String result; if (namespace == null) { - result = TagUtils.buildNamespace(actionMapper, stack, req); + result = getNamespace(stack); } else { result = findString(namespace); } @@ -435,27 +442,32 @@ protected String determineNamespace(String namespace, ValueStack stack, HttpServ return result; } + protected String getNamespace(ValueStack stack) { + ActionContext context = ActionContext.of(stack.getContext()); + ActionInvocation invocation = context.getActionInvocation(); + return invocation.getProxy().getNamespace(); + } + /** * Pushes this component's parameter Map as well as the component itself on to the stack * and then copies the supplied parameters over. Because the component's parameter Map is * pushed before the component itself, any key-value pair that can't be assigned to component * will be set in the parameters Map. * - * @param params the parameters to copy. + * @param attributesToCopy the attributes to copy. */ - public void copyParams(Map params) { - stack.push(parameters); + public void copyAttributes(Map attributesToCopy) { + stack.push(attributes); stack.push(this); try { - for (Object o : params.entrySet()) { - Map.Entry entry = (Map.Entry) o; - String key = (String) entry.getKey(); + for (Map.Entry entry : attributesToCopy.entrySet()) { + String key = entry.getKey(); if (key.indexOf('-') >= 0) { // UI component attributes may contain hypens (e.g. data-ajax), but ognl // can't handle that, and there can't be a component property with a hypen - // so into the parameters map it goes. See WW-4493 - parameters.put(key, entry.getValue()); + // so into the attributes map it goes. See WW-4493 + attributes.put(key, entry.getValue()); } else { stack.setValue(key, entry.getValue()); } @@ -468,31 +480,34 @@ public void copyParams(Map params) { /** * Constructs a string representation of the given exception. - * @param t the exception + * + * @param t the exception * @return the exception as a string. */ protected String toString(Throwable t) { try (FastByteArrayOutputStream bout = new FastByteArrayOutputStream(); - PrintWriter wrt = new PrintWriter(bout)) { + PrintWriter wrt = new PrintWriter(bout)) { t.printStackTrace(wrt); return bout.toString(); } } /** - * Gets the parameters. - * @return the parameters. Is never null. + * Gets the attributes. + * + * @return the attributes. It's never null. */ - public Map getParameters() { - return parameters; + public Map getAttributes() { + return attributes; } /** - * Adds all the given parameters to this component's own parameters. - * @param params the parameters to add. + * Adds all the given attributes to this component's own attributes. + * + * @param additionalAttributes the attributes to add. */ - public void addAllParameters(Map params) { - parameters.putAll(params); + public void addAllAttributes(Map additionalAttributes) { + attributes.putAll(additionalAttributes); } /** @@ -501,12 +516,13 @@ public void addAllParameters(Map params) { * If the provided key is null nothing happens. * If the provided value is null any existing parameter with * the given key name is removed. - * @param key the key of the new parameter to add. + * + * @param key the key of the new parameter to add. * @param value the value associated with the key. */ public void addParameter(String key, Object value) { if (key != null) { - Map params = getParameters(); + Map params = getAttributes(); if (value == null) { params.remove(key); @@ -518,12 +534,23 @@ public void addParameter(String key, Object value) { /** * Overwrite to set if body should be used. + * * @return always false for this component. */ public boolean usesBody() { return false; } + /** + * Override to set if body content should be HTML-escaped. + * + * @return always true (default) for this component. + * @since 6.0.0 + */ + public boolean escapeHtmlBody() { + return escapeHtmlBody; + } + /** * Checks if provided name is a valid tag's attribute * @@ -540,12 +567,13 @@ public boolean isValidTagAttribute(String attrName) { * @return list of attributes */ protected Collection getStandardAttributes() { - Class clz = getClass(); + Class clz = getClass(); Collection standardAttributes = standardAttributesMap.get(clz); if (standardAttributes == null) { - Collection methods = AnnotationUtils.getAnnotatedMethods(clz, StrutsTagAttribute.class); + Collection methods = MethodUtils.getMethodsListWithAnnotation(clz, StrutsTagAttribute.class, + true, true); standardAttributes = new HashSet<>(methods.size()); - for(Method m : methods) { + for (Method m : methods) { standardAttributes.add(StringUtils.uncapitalize(m.getName().substring(3))); } standardAttributesMap.putIfAbsent(clz, standardAttributes); @@ -553,4 +581,43 @@ protected Collection getStandardAttributes() { return standardAttributes; } + /** + * Request that the tag state be cleared during {@link org.apache.struts2.views.jsp.StrutsBodyTagSupport#doEndTag()} processing, + * which may help with certain edge cases with tag logic running on servers that implement JSP Tag Pooling. + * + * Note: All Tag classes that extend {@link org.apache.struts2.views.jsp.StrutsBodyTagSupport} must implement a setter for + * this attribute (same name), and it must be defined at the Tag class level. + * Defining a setter in the superclass alone is insufficient (results in "Cannot find a setter method for the attribute"). + *

      + * See {@link org.apache.struts2.views.jsp.StrutsBodyTagSupport#clearTagStateForTagPoolingServers() for additional details. + * + * @param performClearTagStateForTagPoolingServers true if tag state should be cleared, false otherwise. + */ + @StrutsTagAttribute(description = "Whether to clear all tag state during doEndTag() processing (if applicable)", type = "Boolean", defaultValue = "false") + public void setPerformClearTagStateForTagPoolingServers(boolean performClearTagStateForTagPoolingServers) { + this.performClearTagStateForTagPoolingServers = performClearTagStateForTagPoolingServers; + } + + public boolean getPerformClearTagStateForTagPoolingServers() { + return this.performClearTagStateForTagPoolingServers; + } + + /** + * Checks if expression doesn't contain vulnerable code + * + * @param expression of the component + * @return true|false + * @since 6.0.0 + */ + protected boolean isAcceptableExpression(String expression) { + NotExcludedAcceptedPatternsChecker.IsAllowed isAllowed = notExcludedAcceptedPatterns.isAllowed(expression); + if (isAllowed.isAllowed()) { + return true; + } + + LOG.warn("Expression [{}] isn't allowed by pattern [{}]! See Accepted / Excluded patterns at\n" + + "https://struts.apache.org/security/", expression, isAllowed.getAllowedPattern()); + + return false; + } } diff --git a/core/src/main/java/org/apache/struts2/components/ComponentUrlProvider.java b/core/src/main/java/org/apache/struts2/components/ComponentUrlProvider.java index d8e32c9056..492e7170c0 100644 --- a/core/src/main/java/org/apache/struts2/components/ComponentUrlProvider.java +++ b/core/src/main/java/org/apache/struts2/components/ComponentUrlProvider.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -20,10 +18,10 @@ */ package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.util.Map; /** @@ -52,7 +50,7 @@ public class ComponentUrlProvider implements UrlProvider { protected UrlRenderer urlRenderer; protected Component component; - private Map parameters; + private final Map parameters; /** * @@ -64,180 +62,224 @@ public ComponentUrlProvider(Component component, Map parameters) { this.parameters = parameters; } + @Override public String determineActionURL(String action, String namespace, String method, HttpServletRequest req, HttpServletResponse res, Map parameters, String scheme, boolean includeContext, boolean encodeResult, boolean forceAddSchemeHostAndPort, boolean escapeAmp) { return component.determineActionURL(action, namespace, method, req, res, parameters, scheme, includeContext, encodeResult, forceAddSchemeHostAndPort, escapeAmp); } + @Override public String determineNamespace(String namespace, ValueStack stack, HttpServletRequest req) { return component.determineNamespace(namespace, stack, req); } + @Override public String findString(String expr) { return component.findString(expr); } + @Override public Map getParameters() { return parameters; } + @Override public HttpServletRequest getHttpServletRequest() { return httpServletRequest; } + @Override public void setHttpServletRequest(HttpServletRequest httpServletRequest) { this.httpServletRequest = httpServletRequest; } + @Override public HttpServletResponse getHttpServletResponse() { return httpServletResponse; } + @Override public void setHttpServletResponse(HttpServletResponse httpServletResponse) { this.httpServletResponse = httpServletResponse; } + @Override public String getIncludeParams() { return includeParams; } + @Override public void setIncludeParams(String includeParams) { this.includeParams = includeParams; } + @Override public String getScheme() { return scheme; } + @Override public void setScheme(String scheme) { this.scheme = scheme; } + @Override public boolean isPutInContext() { return component instanceof ContextBean; } + @Override public String getVar() { return isPutInContext() ? ((ContextBean)component).getVar() : null; } + @Override public String getValue() { return value; } + @Override public void setValue(String value) { this.value = value; } + @Override public String getAction() { return action; } + @Override public void setAction(String action) { this.action = action; } + @Override public String getNamespace() { return namespace; } + @Override public void setNamespace(String namespace) { this.namespace = namespace; } + @Override public String getMethod() { return method; } + @Override public void setMethod(String method) { this.method = method; } + @Override public boolean isEncode() { return encode; } + @Override public void setEncode(boolean encode) { this.encode = encode; } + @Override public boolean isIncludeContext() { return includeContext; } + @Override public void setIncludeContext(boolean includeContext) { this.includeContext = includeContext; } + @Override public boolean isEscapeAmp() { return escapeAmp; } + @Override public void setEscapeAmp(boolean escapeAmp) { this.escapeAmp = escapeAmp; } + @Override public String getPortletMode() { return portletMode; } + @Override public void setPortletMode(String portletMode) { this.portletMode = portletMode; } + @Override public String getWindowState() { return windowState; } + @Override public void setWindowState(String windowState) { this.windowState = windowState; } + @Override public String getPortletUrlType() { return portletUrlType; } + @Override public ValueStack getStack() { return component.getStack(); } + @Override public void setPortletUrlType(String portletUrlType) { this.portletUrlType = portletUrlType; } + @Override public String getAnchor() { return anchor; } + @Override public void setAnchor(String anchor) { this.anchor = anchor; } + @Override public boolean isForceAddSchemeHostAndPort() { return forceAddSchemeHostAndPort; } + @Override public void setForceAddSchemeHostAndPort(boolean forceAddSchemeHostAndPort) { this.forceAddSchemeHostAndPort = forceAddSchemeHostAndPort; } + @Override public void putInContext(String result) { if (isPutInContext()) { ((ContextBean)component).putInContext(result); } } + @Override public String getUrlIncludeParams() { return urlIncludeParams; } + @Override public void setUrlIncludeParams(String urlIncludeParams) { this.urlIncludeParams = urlIncludeParams; } + @Override public ExtraParameterProvider getExtraParameterProvider() { return extraParameterProvider; } + @Override public void setExtraParameterProvider(ExtraParameterProvider extraParameterProvider) { this.extraParameterProvider = extraParameterProvider; } @@ -246,6 +288,7 @@ public UrlRenderer getUrlRenderer() { return urlRenderer; } + @Override public void setUrlRenderer(UrlRenderer urlRenderer) { this.urlRenderer = urlRenderer; } diff --git a/core/src/main/java/org/apache/struts2/components/ContextBean.java b/core/src/main/java/org/apache/struts2/components/ContextBean.java index 86f09bfa6b..5d78d6d8ba 100644 --- a/core/src/main/java/org/apache/struts2/components/ContextBean.java +++ b/core/src/main/java/org/apache/struts2/components/ContextBean.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.commons.lang3.StringUtils; import org.apache.struts2.views.annotations.StrutsTagAttribute; @@ -30,7 +27,7 @@ */ public abstract class ContextBean extends Component { protected String var; - + public ContextBean(ValueStack stack) { super(stack); } @@ -40,14 +37,14 @@ protected void putInContext(Object value) { stack.getContext().put(var, value); } } - - @StrutsTagAttribute(description="Name used to reference the value pushed into the Value Stack") + + @StrutsTagAttribute(description="Name used to reference the value pushed into the Value Stack (scope: action).") public void setVar(String var) { if (var != null) { this.var = findString(var); } } - + protected String getVar() { return this.var; } diff --git a/core/src/main/java/org/apache/struts2/components/Date.java b/core/src/main/java/org/apache/struts2/components/Date.java index f1a3c978cb..d009178589 100644 --- a/core/src/main/java/org/apache/struts2/components/Date.java +++ b/core/src/main/java/org/apache/struts2/components/Date.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,29 +16,32 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.TextProvider; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.text.TextProvider; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.struts2.components.date.DateFormatter; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; import java.io.IOException; import java.io.Writer; -import java.text.DateFormat; -import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.ZoneId; +import java.time.ZonedDateTime; import java.util.ArrayList; import java.util.Calendar; import java.util.List; -import java.util.TimeZone; /** * - * + *

      * Format Date object in different ways. *

      * The date tag will allow you to format a Date in a quick and easy way. @@ -59,6 +60,12 @@ *

      * *

      + * Note: Since Struts 6.0.0 a new Java 8 API has been used to format the Date, it's based on + * DateTimeFormatter + * which uses a bit different patterns. + *

      + * + *

      * Configurable attributes are: *

      * @@ -130,8 +137,8 @@ * if one is not found DateFormat.MEDIUM format will be used * * - * - * + *

      + *

      * * *

      Examples

      @@ -145,12 +152,12 @@ * * * Date - * */ -@StrutsTag(name="date", tldBodyContent="empty", tldTagClass="org.apache.struts2.views.jsp.DateTag", description="Render a formatted date.") +@StrutsTag(name = "date", tldBodyContent = "empty", tldTagClass = "org.apache.struts2.views.jsp.DateTag", description = "Render a formatted date.") public class Date extends ContextBean { private static final Logger LOG = LogManager.getLogger(Date.class); + /** * Property name to fall back when no format is specified */ @@ -202,17 +209,18 @@ public class Date extends ContextBean { private String timezone; + private DateFormatter dateFormatter; + public Date(ValueStack stack) { super(stack); } - private TextProvider findProviderInStack() { - for (Object o : getStack().getRoot()) { - if (o instanceof TextProvider) { - return (TextProvider) o; - } - } - return null; + /** + * An instance of {@link DateFormatter} + */ + @Inject + public void setDateFormatter(DateFormatter dateFormatter) { + this.dateFormatter = dateFormatter; } /** @@ -223,11 +231,11 @@ private TextProvider findProviderInStack() { * @param date the date * @return the date nicely */ - public String formatTime(TextProvider tp, java.util.Date date) { - java.util.Date now = new java.util.Date(); + public String formatTime(TextProvider tp, ZonedDateTime date) { + ZonedDateTime now = ZonedDateTime.now(); StringBuilder sb = new StringBuilder(); - List args = new ArrayList(); - long secs = Math.abs((now.getTime() - date.getTime()) / 1000); + List args = new ArrayList<>(); + long secs = Math.abs(now.toEpochSecond() - date.toEpochSecond()); long mins = secs / 60; long sec = secs % 60; int min = (int) mins % 60; @@ -270,7 +278,7 @@ public String formatTime(TextProvider tp, java.util.Date date) { args.clear(); args.add(sb.toString()); - if (date.before(now)) { + if (date.isBefore(now)) { // looks like this date is passed return tp.getText(DATETAG_PROPERTY_PAST, DATETAG_DEFAULT_PAST, args); } else { @@ -278,83 +286,63 @@ public String formatTime(TextProvider tp, java.util.Date date) { } } + @Override public boolean end(Writer writer, String body) { - String msg; - java.util.Date date = null; + TextProvider textProvider = findProviderInStack(); + + ZonedDateTime date = null; + final ZoneId tz = getTimeZone(); // find the name on the valueStack - try { - //support Calendar also - Object dateObject = findValue(name); - if (dateObject instanceof java.util.Date) { - date = (java.util.Date) dateObject; - } else if (dateObject instanceof Calendar) { - date = ((Calendar) dateObject).getTime(); - } else if (dateObject instanceof Long) { - date = new java.util.Date((long) dateObject); - } else { - if (devMode) { - TextProvider tp = findProviderInStack(); - String developerNotification = ""; - if (tp != null) { - developerNotification = findProviderInStack().getText( - "devmode.notification", - "Developer Notification:\n{0}", - new String[]{ - "Expression [" + name + "] passed to tag which was evaluated to [" + dateObject + "](" - + (dateObject != null ? dateObject.getClass() : "null") + ") isn't instance of java.util.Date nor java.util.Calendar nor long!" - } - ); - } - LOG.warn(developerNotification); - } else { - LOG.debug("Expression [{}] passed to tag which was evaluated to [{}]({}) isn't instance of java.util.Date nor java.util.Calendar nor long!", - name, dateObject, (dateObject != null ? dateObject.getClass() : "null")); + Object dateObject = findValue(name); + if (dateObject instanceof java.sql.Date) { + date = ((java.sql.Date) dateObject).toLocalDate().atTime(LocalTime.now(tz)).atZone(tz); + } else if (dateObject instanceof java.sql.Time) { + date = ((java.sql.Time) dateObject).toLocalTime().atDate(ZonedDateTime.now(tz).toLocalDate()).atZone(tz); + } else if (dateObject instanceof java.util.Date) { + date = ((java.util.Date) dateObject).toInstant().atZone(tz); + } else if (dateObject instanceof Calendar) { + date = ((Calendar) dateObject).toInstant().atZone(tz); + } else if (dateObject instanceof Long) { + date = Instant.ofEpochMilli((long) dateObject).atZone(tz); + } else if (dateObject instanceof LocalDateTime) { + date = ((LocalDateTime) dateObject).atZone(tz); + } else if (dateObject instanceof LocalDate) { + date = ((LocalDate) dateObject).atStartOfDay(tz); + } else if (dateObject instanceof LocalTime) { + date = ((LocalTime) dateObject).atDate(ZonedDateTime.now(tz).toLocalDate()).atZone(tz); + } else if (dateObject instanceof Instant) { + date = ((Instant) dateObject).atZone(tz); + } else { + if (devMode) { + String developerNotification = ""; + if (textProvider != null) { + developerNotification = textProvider.getText( + "devmode.notification", + "Developer Notification:\n{0}", + new String[]{ + "Expression [" + name + "] passed to tag which was evaluated to [" + dateObject + "](" + + (dateObject != null ? dateObject.getClass() : "null") + ") isn't supported!" + } + ); } + LOG.warn(developerNotification); + } else { + LOG.debug("Expression [{}] passed to tag which was evaluated to [{}]({}) isn't supported!", + name, dateObject, (dateObject != null ? dateObject.getClass() : "null")); } - } catch (Exception e) { - LOG.error("Could not convert object with key '{}' to a java.util.Date instance", name); } //try to find the format on the stack if (format != null) { format = findString(format); } + String msg; if (date != null) { - TextProvider tp = findProviderInStack(); - if (tp != null) { + if (textProvider != null) { if (nice) { - msg = formatTime(tp, date); + msg = formatTime(textProvider, date); } else { - TimeZone tz = getTimeZone(); - if (format == null) { - String globalFormat = null; - - // if the format is not specified, fall back using the - // defined property DATETAG_PROPERTY - globalFormat = tp.getText(DATETAG_PROPERTY); - - // if tp.getText can not find the property then the - // returned string is the same as input = - // DATETAG_PROPERTY - if (globalFormat != null - && !DATETAG_PROPERTY.equals(globalFormat)) { - SimpleDateFormat sdf = new SimpleDateFormat(globalFormat, - ActionContext.getContext().getLocale()); - sdf.setTimeZone(tz); - msg = sdf.format(date); - } else { - DateFormat df = DateFormat.getDateTimeInstance( - DateFormat.MEDIUM, DateFormat.MEDIUM, - ActionContext.getContext().getLocale()); - df.setTimeZone(tz); - msg = df.format(date); - } - } else { - SimpleDateFormat sdf = new SimpleDateFormat(format, ActionContext - .getContext().getLocale()); - sdf.setTimeZone(tz); - msg = sdf.format(date); - } + msg = formatDate(textProvider, date); } if (msg != null) { try { @@ -372,30 +360,53 @@ public boolean end(Writer writer, String body) { return super.end(writer, ""); } - private TimeZone getTimeZone() { - TimeZone tz = TimeZone.getDefault(); + private String formatDate(TextProvider textProvider, ZonedDateTime date) { + String useFormat = format; + if (useFormat == null) { + // if the format is not specified, fall back using the defined property DATETAG_PROPERTY + useFormat = textProvider.getText(DATETAG_PROPERTY); + if (DATETAG_PROPERTY.equals(useFormat)) { + // if tp.getText can not find the property then the + // returned string is the same as input = DATETAG_PROPERTY + useFormat = null; + } + } + return dateFormatter.format(date, useFormat); + } + + private ZoneId getTimeZone() { + ZoneId tz = ZoneId.systemDefault(); if (timezone != null) { - timezone = stripExpressionIfAltSyntax(timezone); + timezone = stripExpression(timezone); String actualTimezone = (String) getStack().findValue(timezone, String.class); if (actualTimezone != null) { timezone = actualTimezone; } - tz = TimeZone.getTimeZone(timezone); + tz = ZoneId.of(timezone); } return tz; } - @StrutsTagAttribute(description="Date or DateTime format pattern", rtexprvalue=false) + private TextProvider findProviderInStack() { + for (Object o : getStack().getRoot()) { + if (o instanceof TextProvider) { + return (TextProvider) o; + } + } + return null; + } + + @StrutsTagAttribute(description = "Date or DateTime format pattern") public void setFormat(String format) { this.format = format; } - @StrutsTagAttribute(description="Whether to print out the date nicely", type="Boolean", defaultValue="false") + @StrutsTagAttribute(description = "Whether to print out the date nicely", type = "Boolean", defaultValue = "false") public void setNice(boolean nice) { this.nice = nice; } - @StrutsTagAttribute(description = "The specific timezone in which to format the date", required = false) + @StrutsTagAttribute(description = "The specific timezone in which to format the date") public void setTimezone(String timezone) { this.timezone = timezone; } @@ -407,7 +418,7 @@ public String getName() { return name; } - @StrutsTagAttribute(description="The date value to format", required=true) + @StrutsTagAttribute(description = "The date value to format", required = true) public void setName(String name) { this.name = name; } diff --git a/core/src/main/java/org/apache/struts2/components/DateTextField.java b/core/src/main/java/org/apache/struts2/components/DateTextField.java index 0fd3614558..314e376383 100644 --- a/core/src/main/java/org/apache/struts2/components/DateTextField.java +++ b/core/src/main/java/org/apache/struts2/components/DateTextField.java @@ -1,13 +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.struts2.components; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import com.opensymphony.xwork2.util.ValueStack; - @StrutsTag( name="datetextfield", tldTagClass="org.apache.struts2.views.jsp.ui.DateTextFieldTag", @@ -18,7 +34,7 @@ public class DateTextField extends UIBean { * The name of the default template for the DateTextFieldTag */ final public static String TEMPLATE = "datetextfield"; - + protected String format; public DateTextField(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { @@ -37,15 +53,14 @@ protected void evaluateExtraParams() { } } - @StrutsTagAttribute(description="Date format attribute", required=true, type="String") + @StrutsTagAttribute(description="Date format attribute", required=true) public void setFormat(String format) { this.format = format; } - @SuppressWarnings("unchecked") @Override protected Class getValueClassType() { return null; } - + } diff --git a/core/src/main/java/org/apache/struts2/components/Debug.java b/core/src/main/java/org/apache/struts2/components/Debug.java index a76e871915..65c210fa05 100644 --- a/core/src/main/java/org/apache/struts2/components/Debug.java +++ b/core/src/main/java/org/apache/struts2/components/Debug.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,32 +16,33 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.util.reflection.ReflectionProvider; +import org.apache.struts2.StrutsException; +import org.apache.struts2.dispatcher.PrepareOperations; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.ognl.ThreadAllowlist; +import org.apache.struts2.util.CompoundRoot; +import org.apache.struts2.util.ValueStack; +import org.apache.struts2.util.reflection.ReflectionProvider; +import org.apache.struts2.views.annotations.StrutsTag; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.io.Writer; -import java.util.Iterator; -import java.util.Map; import java.util.ArrayList; +import java.util.Iterator; import java.util.List; - -import org.apache.struts2.views.annotations.StrutsTag; -import org.apache.struts2.StrutsException; +import java.util.Map; @StrutsTag(name="debug", tldTagClass="org.apache.struts2.views.jsp.ui.DebugTag", - description="Prints debugging information") + description="Prints debugging information (Only if 'struts.devMode' is enabled)") public class Debug extends UIBean { public static final String TEMPLATE = "debug"; - + protected ReflectionProvider reflectionProvider; - + private ThreadAllowlist threadAllowlist; public Debug(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { super(stack, request, response); @@ -53,7 +52,12 @@ public Debug(ValueStack stack, HttpServletRequest request, HttpServletResponse r public void setReflectionProvider(ReflectionProvider prov) { this.reflectionProvider = prov; } - + + @Inject + public void setThreadAllowlist(ThreadAllowlist threadAllowlist) { + this.threadAllowlist = threadAllowlist; + } + protected String getDefaultTemplate() { return TEMPLATE; } @@ -61,42 +65,71 @@ protected String getDefaultTemplate() { public boolean start(Writer writer) { boolean result = super.start(writer); - ValueStack stack = getStack(); - Iterator iter = stack.getRoot().iterator(); - List stackValues = new ArrayList(stack.getRoot().size()); - while (iter.hasNext()) { - Object o = iter.next(); - Map values; - try { - values = reflectionProvider.getBeanMap(o); - } catch (Exception e) { - throw new StrutsException("Caught an exception while getting the property values of " + o, e); + if (showDebug()) { + ValueStack stack = getStack(); + allowList(stack.getRoot()); + + Iterator iter = stack.getRoot().iterator(); + List stackValues = new ArrayList<>(stack.getRoot().size()); + while (iter.hasNext()) { + Object o = iter.next(); + Map values; + try { + values = reflectionProvider.getBeanMap(o); + } catch (Exception e) { + throw new StrutsException("Caught an exception while getting the property values of " + o, e); + } + allowListClass(o); + stackValues.add(new DebugMapEntry(o.getClass().getName(), values)); } - stackValues.add(new DebugMapEntry(o.getClass().getName(), values)); + + addParameter("stackValues", stackValues); } + return result; + } - addParameter("stackValues", stackValues); + private void allowList(CompoundRoot root) { + root.forEach(this::allowListClass); + } - return result; + private void allowListClass(Object o) { + threadAllowlist.allowClassHierarchy(o.getClass()); + } + + @Override + public boolean end(Writer writer, String body) { + if (showDebug()) { + return super.end(writer, body); + } else { + popComponentStack(); + return false; + } + } + + protected boolean showDebug() { + return (devMode || Boolean.TRUE == PrepareOperations.getDevModeOverride()); } - private static class DebugMapEntry implements Map.Entry { - private Object key; + private static class DebugMapEntry implements Map.Entry { + private final String key; private Object value; - DebugMapEntry(Object key, Object value) { + DebugMapEntry(String key, Object value) { this.key = key; this.value = value; } - public Object getKey() { + @Override + public String getKey() { return key; } + @Override public Object getValue() { return value; } + @Override public Object setValue(Object newVal) { Object oldVal = value; value = newVal; diff --git a/core/src/main/java/org/apache/struts2/components/DoubleListUIBean.java b/core/src/main/java/org/apache/struts2/components/DoubleListUIBean.java index 5383a53414..56a1de8a7f 100644 --- a/core/src/main/java/org/apache/struts2/components/DoubleListUIBean.java +++ b/core/src/main/java/org/apache/struts2/components/DoubleListUIBean.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,30 +16,28 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.util.Map; /** *

      * DoubleListUIBean is the standard superclass of all Struts double list handling components. *

      - * + *

      * *

      * Note that the doublelistkey and doublelistvalue attribute will default to "key" and "value" * respectively only when the doublelist attribute is evaluated to a Map or its descendant. * Other thing else, will result in doublelistkey and doublelistvalue to be null and not used. *

      - * + *

      * - * */ public abstract class DoubleListUIBean extends ListUIBean { @@ -140,21 +136,21 @@ public void evaluateExtraParams() { Object tmpDoubleList = findValue(doubleList); if (doubleListKey != null) { addParameter("doubleListKey", doubleListKey); - }else if (tmpDoubleList instanceof Map) { + } else if (tmpDoubleList instanceof Map) { addParameter("doubleListKey", "key"); } if (doubleListValue != null) { - doubleListValue = stripExpressionIfAltSyntax(doubleListValue); + doubleListValue = stripExpression(doubleListValue); addParameter("doubleListValue", doubleListValue); - }else if (tmpDoubleList instanceof Map) { + } else if (tmpDoubleList instanceof Map) { addParameter("doubleListValue", "value"); } if (doubleListCssClass != null) { addParameter("doubleListCssClass", findString(doubleListCssClass)); } - if (doubleListCssStyle!= null) { + if (doubleListCssStyle != null) { addParameter("doubleListCssStyle", findString(doubleListCssStyle)); } if (doubleListTitle != null) { @@ -168,11 +164,11 @@ public void evaluateExtraParams() { // ok, let's look it up Component form = findAncestor(Form.class); if (form != null) { - addParameter("formName", form.getParameters().get("name")); + addParameter("formName", form.getAttributes().get("name")); } } - Class valueClazz = getValueClassType(); + Class valueClazz = getValueClassType(); if (valueClazz != null) { if (doubleValue != null) { @@ -190,10 +186,9 @@ public void evaluateExtraParams() { Form form = (Form) findAncestor(Form.class); if (doubleId != null) { - // this check is needed for backwards compatibility with 2.1.x - addParameter("doubleId", findStringIfAltSyntax(doubleId)); + addParameter("doubleId", findString(doubleId)); } else if (form != null) { - addParameter("doubleId", form.getParameters().get("id") + "_" +escape(doubleName !=null ? findString(doubleName) : null)); + addParameter("doubleId", form.getAttributes().get("id") + "_" + escape(doubleName != null ? findString(doubleName) : null)); } else { addParameter("doubleId", escape(doubleName != null ? findString(doubleName) : null)); } @@ -272,23 +267,23 @@ public void evaluateExtraParams() { } } - @StrutsTagAttribute(description="The second iterable source to populate from.", required=true) + @StrutsTagAttribute(description = "The second iterable source to populate from.", required = true) public void setDoubleList(String doubleList) { this.doubleList = doubleList; } - @StrutsTagAttribute(description="The key expression to use for second list") + @StrutsTagAttribute(description = "The key expression to use for second list") public void setDoubleListKey(String doubleListKey) { this.doubleListKey = doubleListKey; } - @StrutsTagAttribute(description="The value expression to use for second list") + @StrutsTagAttribute(description = "The value expression to use for second list") public void setDoubleListValue(String doubleListValue) { this.doubleListValue = doubleListValue; } @StrutsTagAttribute(description = "Property of second list objects to get css class from") - public void setDoubleListCssClass(String doubleListCssClass) { + public void setDoubleListCssClass(String doubleListCssClass) { this.doubleListCssClass = doubleListCssClass; } @@ -302,17 +297,17 @@ public void setDoubleListTitle(String doubleListTitle) { this.doubleListTitle = doubleListTitle; } - @StrutsTagAttribute(description="The name for complete component", required=true) + @StrutsTagAttribute(description = "The name for complete component", required = true) public void setDoubleName(String doubleName) { this.doubleName = doubleName; } - @StrutsTagAttribute(description="The value expression for complete component") + @StrutsTagAttribute(description = "The value expression for complete component") public void setDoubleValue(String doubleValue) { this.doubleValue = doubleValue; } - @StrutsTagAttribute(description="The form name this component resides in and populates to") + @StrutsTagAttribute(description = "The form name this component resides in and populates to") public void setFormName(String formName) { this.formName = formName; } @@ -321,7 +316,7 @@ public String getFormName() { return formName; } - @StrutsTagAttribute(description="The css class for the second list") + @StrutsTagAttribute(description = "The css class for the second list") public void setDoubleCssClass(String doubleCssClass) { this.doubleCssClass = doubleCssClass; } @@ -330,7 +325,7 @@ public String getDoubleCssClass() { return doubleCssClass; } - @StrutsTagAttribute(description="The css style for the second list") + @StrutsTagAttribute(description = "The css style for the second list") public void setDoubleCssStyle(String doubleCssStyle) { this.doubleCssStyle = doubleCssStyle; } @@ -339,7 +334,7 @@ public String getDoubleCssStyle() { return doubleCssStyle; } - @StrutsTagAttribute(description="The header key for the second list") + @StrutsTagAttribute(description = "The header key for the second list") public void setDoubleHeaderKey(String doubleHeaderKey) { this.doubleHeaderKey = doubleHeaderKey; } @@ -348,7 +343,7 @@ public String getDoubleHeaderKey() { return doubleHeaderKey; } - @StrutsTagAttribute(description="The header value for the second list") + @StrutsTagAttribute(description = "The header value for the second list") public void setDoubleHeaderValue(String doubleHeaderValue) { this.doubleHeaderValue = doubleHeaderValue; } @@ -357,7 +352,7 @@ public String getDoubleHeaderValue() { return doubleHeaderValue; } - @StrutsTagAttribute(description="Decides if the second list will add an empty option") + @StrutsTagAttribute(description = "Decides if the second list will add an empty option") public void setDoubleEmptyOption(String doubleEmptyOption) { this.doubleEmptyOption = doubleEmptyOption; } @@ -371,7 +366,7 @@ public String getDoubleDisabled() { return doubleDisabled; } - @StrutsTagAttribute(description="Decides if a disable attribute should be added to the second list") + @StrutsTagAttribute(description = "Decides if a disable attribute should be added to the second list") public void setDoubleDisabled(String doubleDisabled) { this.doubleDisabled = doubleDisabled; } @@ -380,7 +375,7 @@ public String getDoubleId() { return doubleId; } - @StrutsTagAttribute(description="The id of the second list") + @StrutsTagAttribute(description = "The id of the second list") public void setDoubleId(String doubleId) { this.doubleId = doubleId; } @@ -389,7 +384,7 @@ public String getDoubleMultiple() { return doubleMultiple; } - @StrutsTagAttribute(description=" Decides if multiple attribute should be set on the second list") + @StrutsTagAttribute(description = " Decides if multiple attribute should be set on the second list") public void setDoubleMultiple(String doubleMultiple) { this.doubleMultiple = doubleMultiple; } @@ -398,7 +393,7 @@ public String getDoubleOnblur() { return doubleOnblur; } - @StrutsTagAttribute(description="Set the onblur attribute of the second list") + @StrutsTagAttribute(description = "Set the onblur attribute of the second list") public void setDoubleOnblur(String doubleOnblur) { this.doubleOnblur = doubleOnblur; } @@ -407,7 +402,7 @@ public String getDoubleOnchange() { return doubleOnchange; } - @StrutsTagAttribute(description="Set the onchange attribute of the second list") + @StrutsTagAttribute(description = "Set the onchange attribute of the second list") public void setDoubleOnchange(String doubleOnchange) { this.doubleOnchange = doubleOnchange; } @@ -416,7 +411,7 @@ public String getDoubleOnclick() { return doubleOnclick; } - @StrutsTagAttribute(description="Set the onclick attribute of the second list") + @StrutsTagAttribute(description = "Set the onclick attribute of the second list") public void setDoubleOnclick(String doubleOnclick) { this.doubleOnclick = doubleOnclick; } @@ -425,7 +420,7 @@ public String getDoubleOndblclick() { return doubleOndblclick; } - @StrutsTagAttribute(description="Set the ondbclick attribute of the second list") + @StrutsTagAttribute(description = "Set the ondbclick attribute of the second list") public void setDoubleOndblclick(String doubleOndblclick) { this.doubleOndblclick = doubleOndblclick; } @@ -434,7 +429,7 @@ public String getDoubleOnfocus() { return doubleOnfocus; } - @StrutsTagAttribute(description="Set the onfocus attribute of the second list") + @StrutsTagAttribute(description = "Set the onfocus attribute of the second list") public void setDoubleOnfocus(String doubleOnfocus) { this.doubleOnfocus = doubleOnfocus; } @@ -443,7 +438,7 @@ public String getDoubleOnkeydown() { return doubleOnkeydown; } - @StrutsTagAttribute(description="Set the onkeydown attribute of the second list") + @StrutsTagAttribute(description = "Set the onkeydown attribute of the second list") public void setDoubleOnkeydown(String doubleOnkeydown) { this.doubleOnkeydown = doubleOnkeydown; } @@ -452,7 +447,7 @@ public String getDoubleOnkeypress() { return doubleOnkeypress; } - @StrutsTagAttribute(description="Set the onkeypress attribute of the second list") + @StrutsTagAttribute(description = "Set the onkeypress attribute of the second list") public void setDoubleOnkeypress(String doubleOnkeypress) { this.doubleOnkeypress = doubleOnkeypress; } @@ -461,7 +456,7 @@ public String getDoubleOnkeyup() { return doubleOnkeyup; } - @StrutsTagAttribute(description="Set the onkeyup attribute of the second list") + @StrutsTagAttribute(description = "Set the onkeyup attribute of the second list") public void setDoubleOnkeyup(String doubleOnkeyup) { this.doubleOnkeyup = doubleOnkeyup; } @@ -470,7 +465,7 @@ public String getDoubleOnmousedown() { return doubleOnmousedown; } - @StrutsTagAttribute(description="Set the onmousedown attribute of the second list") + @StrutsTagAttribute(description = "Set the onmousedown attribute of the second list") public void setDoubleOnmousedown(String doubleOnmousedown) { this.doubleOnmousedown = doubleOnmousedown; } @@ -479,7 +474,7 @@ public String getDoubleOnmousemove() { return doubleOnmousemove; } - @StrutsTagAttribute(description="Set the onmousemove attribute of the second list") + @StrutsTagAttribute(description = "Set the onmousemove attribute of the second list") public void setDoubleOnmousemove(String doubleOnmousemove) { this.doubleOnmousemove = doubleOnmousemove; } @@ -488,7 +483,7 @@ public String getDoubleOnmouseout() { return doubleOnmouseout; } - @StrutsTagAttribute(description="Set the onmouseout attribute of the second list") + @StrutsTagAttribute(description = "Set the onmouseout attribute of the second list") public void setDoubleOnmouseout(String doubleOnmouseout) { this.doubleOnmouseout = doubleOnmouseout; } @@ -497,7 +492,7 @@ public String getDoubleOnmouseover() { return doubleOnmouseover; } - @StrutsTagAttribute(description="Set the onmouseover attribute of the second list") + @StrutsTagAttribute(description = "Set the onmouseover attribute of the second list") public void setDoubleOnmouseover(String doubleOnmouseover) { this.doubleOnmouseover = doubleOnmouseover; } @@ -506,7 +501,7 @@ public String getDoubleOnmouseup() { return doubleOnmouseup; } - @StrutsTagAttribute(description="Set the onmouseup attribute of the second list") + @StrutsTagAttribute(description = "Set the onmouseup attribute of the second list") public void setDoubleOnmouseup(String doubleOnmouseup) { this.doubleOnmouseup = doubleOnmouseup; } @@ -515,7 +510,7 @@ public String getDoubleOnselect() { return doubleOnselect; } - @StrutsTagAttribute(description="Set the onselect attribute of the second list") + @StrutsTagAttribute(description = "Set the onselect attribute of the second list") public void setDoubleOnselect(String doubleOnselect) { this.doubleOnselect = doubleOnselect; } @@ -524,7 +519,7 @@ public String getDoubleSize() { return doubleSize; } - @StrutsTagAttribute(description="Set the size attribute of the second list") + @StrutsTagAttribute(description = "Set the size attribute of the second list") public void setDoubleSize(String doubleSize) { this.doubleSize = doubleSize; } @@ -549,36 +544,36 @@ public String getDoubleValue() { return doubleValue; } - @StrutsTagAttribute(description="Decides of an empty option is to be inserted in the second list", type="Boolean", defaultValue="false") + @StrutsTagAttribute(description = "Decides of an empty option is to be inserted in the second list", type = "Boolean", defaultValue = "false") public void setEmptyOption(String emptyOption) { this.emptyOption = emptyOption; } - @StrutsTagAttribute(description="Set the header key of the second list. Must not be empty! " + - "'-1' and '' is correct, '' is bad.") + @StrutsTagAttribute(description = "Set the header key of the second list. Must not be empty! " + + "'-1' and '' is correct, '' is bad.") public void setHeaderKey(String headerKey) { this.headerKey = headerKey; } - @StrutsTagAttribute(description=" Set the header value of the second list") + @StrutsTagAttribute(description = " Set the header value of the second list") public void setHeaderValue(String headerValue) { this.headerValue = headerValue; } - @StrutsTagAttribute(description="Creates a multiple select. " + - "The tag will pre-select multiple values if the values are passed as an Array " + - "(of appropriate types) via the value attribute.") + @StrutsTagAttribute(description = "Creates a multiple select. " + + "The tag will pre-select multiple values if the values are passed as an Array " + + "(of appropriate types) via the value attribute.") public void setMultiple(String multiple) { // TODO: Passing a Collection may work too? this.multiple = multiple; } - @StrutsTagAttribute(description="Size of the element box (# of elements to show)", type="Integer") + @StrutsTagAttribute(description = "Size of the element box (# of elements to show)", type = "Integer") public void setSize(String size) { this.size = size; } - @StrutsTagAttribute(description="Set the html accesskey attribute.") + @StrutsTagAttribute(description = "Set the html accesskey attribute.") public void setDoubleAccesskey(String doubleAccesskey) { this.doubleAccesskey = doubleAccesskey; } diff --git a/core/src/main/java/org/apache/struts2/components/DoubleSelect.java b/core/src/main/java/org/apache/struts2/components/DoubleSelect.java index 539d3aef21..2cb5ecf96a 100644 --- a/core/src/main/java/org/apache/struts2/components/DoubleSelect.java +++ b/core/src/main/java/org/apache/struts2/components/DoubleSelect.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,15 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.commons.lang3.StringUtils; import org.apache.struts2.views.annotations.StrutsTag; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** * @@ -60,7 +57,7 @@ protected String getDefaultTemplate() { public void evaluateExtraParams() { super.evaluateExtraParams(); StringBuilder onchangeParam = new StringBuilder(); - onchangeParam.append(getParameters().get("id")).append("Redirect(this.selectedIndex)"); + onchangeParam.append(getAttributes().get("id")).append("Redirect(this.selectedIndex)"); if(StringUtils.isNotEmpty(this.onchange)) { onchangeParam.append(";").append(this.onchange); } diff --git a/core/src/main/java/org/apache/struts2/components/Else.java b/core/src/main/java/org/apache/struts2/components/Else.java index 4ce124bac0..9f00a3a700 100644 --- a/core/src/main/java/org/apache/struts2/components/Else.java +++ b/core/src/main/java/org/apache/struts2/components/Else.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.struts2.views.annotations.StrutsTag; import java.io.Writer; diff --git a/core/src/main/java/org/apache/struts2/components/ElseIf.java b/core/src/main/java/org/apache/struts2/components/ElseIf.java index 215a58ee7c..f98914c568 100644 --- a/core/src/main/java/org/apache/struts2/components/ElseIf.java +++ b/core/src/main/java/org/apache/struts2/components/ElseIf.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; diff --git a/core/src/main/java/org/apache/struts2/components/ExtraParameterProvider.java b/core/src/main/java/org/apache/struts2/components/ExtraParameterProvider.java index 844e6d62b4..1d37195500 100644 --- a/core/src/main/java/org/apache/struts2/components/ExtraParameterProvider.java +++ b/core/src/main/java/org/apache/struts2/components/ExtraParameterProvider.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -23,5 +21,7 @@ import java.util.Map; public interface ExtraParameterProvider { - public Map getExtraParameters(); + + Map getExtraParameters(); + } diff --git a/core/src/main/java/org/apache/struts2/components/FieldError.java b/core/src/main/java/org/apache/struts2/components/FieldError.java index 809253a8a0..65a742026c 100644 --- a/core/src/main/java/org/apache/struts2/components/FieldError.java +++ b/core/src/main/java/org/apache/struts2/components/FieldError.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.components.Param.UnnamedParametric; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.util.ArrayList; import java.util.List; @@ -90,7 +87,7 @@ "or partial depending on param tag nested)if they exists") public class FieldError extends UIBean implements UnnamedParametric { - private List errorFieldNames = new ArrayList<>(); + private final List errorFieldNames = new ArrayList<>(); private boolean escape = true; public FieldError(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { @@ -123,7 +120,7 @@ public List getFieldErrorFieldNames() { return errorFieldNames; } - @StrutsTagAttribute(description="Field name for single field attribute usage", type="String") + @StrutsTagAttribute(description="Field name for single field attribute usage") public void setFieldName(String fieldName) { addParameter(fieldName); } diff --git a/core/src/main/java/org/apache/struts2/components/File.java b/core/src/main/java/org/apache/struts2/components/File.java index 752c31c824..e9317afba4 100644 --- a/core/src/main/java/org/apache/struts2/components/File.java +++ b/core/src/main/java/org/apache/struts2/components/File.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,18 +16,16 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - /** * * Renders an HTML file input element. @@ -71,13 +67,13 @@ public void evaluateParams() { Form form = (Form) findAncestor(Form.class); if (form != null) { - String encType = (String) form.getParameters().get("enctype"); + String encType = (String) form.getAttributes().get("enctype"); if (!"multipart/form-data".equals(encType)) { // uh oh, this isn't good! Let's warn the developer LOG.warn("Struts has detected a file upload UI tag (s:file) being used without a form set to enctype 'multipart/form-data'. This is probably an error!"); } - String method = (String) form.getParameters().get("method"); + String method = (String) form.getAttributes().get("method"); if (!"post".equalsIgnoreCase(method)) { // uh oh, this isn't good! Let's warn the developer LOG.warn("Struts has detected a file upload UI tag (s:file) being used without a form set to method 'POST'. This is probably an error!"); @@ -98,8 +94,14 @@ public void setAccept(String accept) { this.accept = accept; } - @StrutsTagAttribute(description="HTML size attribute", required=false, type="Integer") + @StrutsTagAttribute(description="HTML size attribute", type="Integer") public void setSize(String size) { this.size = size; } + + @Override + @StrutsTagAttribute(description="Ignored during file upload") + public void setValue(String value) { + // ignores provided value + } } diff --git a/core/src/main/java/org/apache/struts2/components/Form.java b/core/src/main/java/org/apache/struts2/components/Form.java index 13247a9cae..7db1477c32 100644 --- a/core/src/main/java/org/apache/struts2/components/Form.java +++ b/core/src/main/java/org/apache/struts2/components/Form.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,27 +16,30 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.ObjectFactory; -import com.opensymphony.xwork2.config.Configuration; -import com.opensymphony.xwork2.config.RuntimeConfiguration; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.config.entities.InterceptorMapping; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.interceptor.MethodFilterInterceptorUtil; -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.validator.*; -import com.opensymphony.xwork2.validator.validators.VisitorFieldValidator; +import org.apache.struts2.ObjectFactory; +import org.apache.struts2.config.Configuration; +import org.apache.struts2.config.RuntimeConfiguration; +import org.apache.struts2.config.entities.ActionConfig; +import org.apache.struts2.config.entities.InterceptorMapping; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.interceptor.MethodFilterInterceptorUtil; +import org.apache.struts2.util.ValueStack; +import org.apache.struts2.validator.ActionValidatorManager; +import org.apache.struts2.validator.FieldValidator; +import org.apache.struts2.validator.ValidationException; +import org.apache.struts2.validator.ValidationInterceptor; +import org.apache.struts2.validator.Validator; +import org.apache.struts2.validator.ValidatorContext; +import org.apache.struts2.validator.validators.VisitorFieldValidator; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.struts2.dispatcher.mapper.ActionMapping; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import org.apache.struts2.views.jsp.TagUtils; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Collections; @@ -75,7 +76,7 @@ * from it and using UrlHelper to generate the final url. * * - * + *

      * * *

      Examples

      @@ -87,13 +88,12 @@ * * * - * */ @StrutsTag( - name="form", - tldTagClass="org.apache.struts2.views.jsp.ui.FormTag", - description="Renders an input form", - allowDynamicAttributes=true) + name = "form", + tldTagClass = "org.apache.struts2.views.jsp.ui.FormTag", + description = "Renders an input form", + allowDynamicAttributes = true) public class Form extends ClosingUIBean { public static final String OPEN_TEMPLATE = "form"; public static final String TEMPLATE = "form-close"; @@ -150,7 +150,7 @@ public void setObjectFactory(ObjectFactory objectFactory) { @Inject public void setUrlRenderer(UrlRenderer urlRenderer) { - this.urlRenderer = urlRenderer; + this.urlRenderer = urlRenderer; } @Inject @@ -160,9 +160,9 @@ public void setActionValidatorManager(ActionValidatorManager mgr) { /* - * Revised for Portlet actionURL as form action, and add wwAction as hidden - * field. Refer to template.simple/form.vm - */ + * Revised for Portlet actionURL as form action, and add wwAction as hidden + * field. Refer to template.simple/form.vm + */ @Override protected void evaluateExtraParams() { super.evaluateExtraParams(); @@ -172,10 +172,10 @@ protected void evaluateExtraParams() { if (name == null) { //make the name the same as the id - String id = (String) getParameters().get("id"); - if (StringUtils.isNotEmpty(id)) { + String id = (String) getAttributes().get("id"); + if (StringUtils.isNotEmpty(id)) { addParameter("name", id); - } + } } if (onsubmit != null) { @@ -204,7 +204,7 @@ protected void evaluateExtraParams() { // keep a collection of the tag names for anything special the templates might want to do (such as pure client // side validation) - if (!parameters.containsKey("tagNames")) { + if (!attributes.containsKey("tagNames")) { // we have this if check so we don't do this twice (on open and close of the template) addParameter("tagNames", new ArrayList()); } @@ -224,7 +224,7 @@ protected void evaluateExtraParams() { @Override protected void populateComponentHtmlId(Form form) { if (id != null) { - addParameter("id", escape(id)); + super.populateComponentHtmlId(null); } // if no id given, it will be tried to generate it from the action attribute @@ -234,14 +234,15 @@ protected void populateComponentHtmlId(Form form) { /** * Evaluate client side JavaScript Enablement. - * @param actionName the actioName to check for - * @param namespace the namespace to check for + * + * @param actionName the actioName to check for + * @param namespace the namespace to check for * @param actionMethod the method to ckeck for */ protected void evaluateClientSideJsEnablement(String actionName, String namespace, String actionMethod) { // Only evaluate if Client-Side js is to be enable when validate=true - Boolean validate = (Boolean) getParameters().get("validate"); + Boolean validate = (Boolean) getAttributes().get("validate"); if (validate != null && validate) { addParameter("performValidation", Boolean.FALSE); @@ -252,11 +253,10 @@ protected void evaluateClientSideJsEnablement(String actionName, String namespac if (actionConfig != null) { List interceptors = actionConfig.getInterceptors(); for (InterceptorMapping interceptorMapping : interceptors) { - if (ValidationInterceptor.class.isInstance(interceptorMapping.getInterceptor())) { - ValidationInterceptor validationInterceptor = (ValidationInterceptor) interceptorMapping.getInterceptor(); + if (interceptorMapping.getInterceptor() instanceof ValidationInterceptor validationInterceptor) { - Set excludeMethods = validationInterceptor.getExcludeMethodsSet(); - Set includeMethods = validationInterceptor.getIncludeMethodsSet(); + Set excludeMethods = validationInterceptor.getExcludeMethodsSet(); + Set includeMethods = validationInterceptor.getIncludeMethodsSet(); if (MethodFilterInterceptorUtil.applyMethod(excludeMethods, includeMethods, actionMethod)) { addParameter("performValidation", Boolean.TRUE); @@ -269,20 +269,29 @@ protected void evaluateClientSideJsEnablement(String actionName, String namespac } public List getValidators(String name) { - Class actionClass = (Class) getParameters().get("actionClass"); + Class actionClass = (Class) getAttributes().get("actionClass"); if (actionClass == null) { return Collections.EMPTY_LIST; } String formActionValue = findString(action); ActionMapping mapping = actionMapper.getMappingFromActionName(formActionValue); + + if (mapping == null) { + mapping = actionMapper.getMappingFromActionName((String) getAttributes().get("actionName")); + } + + if (mapping == null) { + return Collections.EMPTY_LIST; + } + String actionName = mapping.getName(); String methodName = null; if (isValidateAnnotatedMethodOnly(actionName)) { methodName = mapping.getMethod(); } - + List actionValidators = actionValidatorManager.getValidators(actionClass, actionName, methodName); List validators = new ArrayList<>(); @@ -293,14 +302,13 @@ public List getValidators(String name) { private boolean isValidateAnnotatedMethodOnly(String actionName) { RuntimeConfiguration runtimeConfiguration = configuration.getRuntimeConfiguration(); - String actionNamespace = TagUtils.buildNamespace(actionMapper, stack, request); + String actionNamespace = getNamespace(stack); ActionConfig actionConfig = runtimeConfiguration.getActionConfig(actionNamespace, actionName); if (actionConfig != null) { List interceptors = actionConfig.getInterceptors(); for (InterceptorMapping interceptorMapping : interceptors) { - if (ValidationInterceptor.class.isInstance(interceptorMapping.getInterceptor())) { - ValidationInterceptor validationInterceptor = (ValidationInterceptor) interceptorMapping.getInterceptor(); + if (interceptorMapping.getInterceptor() instanceof ValidationInterceptor validationInterceptor) { return validationInterceptor.isValidateAnnotatedMethodOnly(); } } @@ -312,8 +320,7 @@ private void findFieldValidators(String name, Class actionClass, String actionNa List validatorList, List resultValidators, String prefix) { for (Validator validator : validatorList) { - if (validator instanceof FieldValidator) { - FieldValidator fieldValidator = (FieldValidator) validator; + if (validator instanceof FieldValidator fieldValidator) { if (validator instanceof VisitorFieldValidator) { VisitorFieldValidator vfValidator = (VisitorFieldValidator) fieldValidator; @@ -349,64 +356,84 @@ private void findFieldValidators(String name, Class actionClass, String actionNa public static class FieldVisitorValidatorWrapper implements FieldValidator { private FieldValidator fieldValidator; private String namePrefix; + public FieldVisitorValidatorWrapper(FieldValidator fv, String namePrefix) { this.fieldValidator = fv; this.namePrefix = namePrefix; } + public String getValidatorType() { return "field-visitor"; } + public String getFieldName() { return namePrefix + fieldValidator.getFieldName(); } + public FieldValidator getFieldValidator() { return fieldValidator; } + public void setFieldValidator(FieldValidator fieldValidator) { this.fieldValidator = fieldValidator; } + public String getDefaultMessage() { return fieldValidator.getDefaultMessage(); } + public String getMessage(Object object) { return fieldValidator.getMessage(object); } + public String getMessageKey() { return fieldValidator.getMessageKey(); } + public String[] getMessageParameters() { return fieldValidator.getMessageParameters(); } + public ValidatorContext getValidatorContext() { return fieldValidator.getValidatorContext(); } + public void setDefaultMessage(String message) { fieldValidator.setDefaultMessage(message); } + public void setFieldName(String fieldName) { fieldValidator.setFieldName(fieldName); } + public void setMessageKey(String key) { fieldValidator.setMessageKey(key); } + public void setMessageParameters(String[] messageParameters) { fieldValidator.setMessageParameters(messageParameters); } + public void setValidatorContext(ValidatorContext validatorContext) { fieldValidator.setValidatorContext(validatorContext); } + public void setValidatorType(String type) { fieldValidator.setValidatorType(type); } + public void setValueStack(ValueStack stack) { fieldValidator.setValueStack(stack); } + public void validate(Object object) throws ValidationException { fieldValidator.validate(object); } + public String getNamePrefix() { return namePrefix; } + public void setNamePrefix(String namePrefix) { this.namePrefix = namePrefix; } @@ -415,7 +442,7 @@ public void setNamePrefix(String namePrefix) { /** * Return type of visited object. * - * @param actionClass action class + * @param actionClass action class * @param visitorFieldName field name * @return type of visited object */ @@ -426,7 +453,7 @@ protected Class getVisitorReturnType(Class actionClass, String visitorFieldName) } String methodName = "get" + StringUtils.capitalize(visitorFieldName); try { - Method method = actionClass.getMethod(methodName, new Class[0]); + Method method = actionClass.getMethod(methodName); return method.getReturnType(); } catch (NoSuchMethodException e) { return null; @@ -445,68 +472,68 @@ protected int getSequence() { return sequence++; } - @StrutsTagAttribute(description="HTML onsubmit attribute") + @StrutsTagAttribute(description = "HTML onsubmit attribute") public void setOnsubmit(String onsubmit) { this.onsubmit = onsubmit; } - @StrutsTagAttribute(description="HTML onreset attribute") + @StrutsTagAttribute(description = "HTML onreset attribute") public void setOnreset(String onreset) { this.onreset = onreset; } - @StrutsTagAttribute(description="Set action name to submit to, without .action suffix", defaultValue="current action") + @StrutsTagAttribute(description = "Set action name to submit to, without .action suffix", defaultValue = "current action") public void setAction(String action) { this.action = action; } - @StrutsTagAttribute(description="HTML form target attribute") + @StrutsTagAttribute(description = "HTML form target attribute") public void setTarget(String target) { this.target = target; } - @StrutsTagAttribute(description="HTML form enctype attribute") + @StrutsTagAttribute(description = "HTML form enctype attribute") public void setEnctype(String enctype) { this.enctype = enctype; } - @StrutsTagAttribute(description="HTML form method attribute") + @StrutsTagAttribute(description = "HTML form method attribute") public void setMethod(String method) { this.method = method; } - @StrutsTagAttribute(description="Namespace for action to submit to", defaultValue="current namespace") + @StrutsTagAttribute(description = "Namespace for action to submit to", defaultValue = "current namespace") public void setNamespace(String namespace) { this.namespace = namespace; } - @StrutsTagAttribute(description="Whether client side/remote validation should be performed. Only" + - " useful with theme xhtml/ajax", type="Boolean", defaultValue="false") + @StrutsTagAttribute(description = "Whether client side/remote validation should be performed. Only" + + " useful with theme xhtml/ajax", type = "Boolean", defaultValue = "false") public void setValidate(String validate) { this.validate = validate; } - @StrutsTagAttribute(description="The portlet mode to display after the form submit") + @StrutsTagAttribute(description = "The portlet mode to display after the form submit") public void setPortletMode(String portletMode) { this.portletMode = portletMode; } - @StrutsTagAttribute(description="The window state to display after the form submit") + @StrutsTagAttribute(description = "The window state to display after the form submit") public void setWindowState(String windowState) { this.windowState = windowState; } - @StrutsTagAttribute(description="The accepted charsets for this form. The values may be comma or blank delimited.") + @StrutsTagAttribute(description = "The accepted charsets for this form. The values may be comma or blank delimited.") public void setAcceptcharset(String acceptcharset) { this.acceptcharset = acceptcharset; } - @StrutsTagAttribute(description="Id of element that will receive the focus when page loads.") + @StrutsTagAttribute(description = "Id of element that will receive the focus when page loads.") public void setFocusElement(String focusElement) { this.focusElement = focusElement; } - @StrutsTagAttribute(description="Whether actual context should be included in URL", type="Boolean", defaultValue="true") + @StrutsTagAttribute(description = "Whether actual context should be included in URL", type = "Boolean", defaultValue = "true") public void setIncludeContext(boolean includeContext) { this.includeContext = includeContext; } diff --git a/core/src/main/java/org/apache/struts2/components/FormButton.java b/core/src/main/java/org/apache/struts2/components/FormButton.java index ab99679cdc..d46828db51 100644 --- a/core/src/main/java/org/apache/struts2/components/FormButton.java +++ b/core/src/main/java/org/apache/struts2/components/FormButton.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,27 +16,22 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - -import org.apache.struts2.views.annotations.StrutsTagAttribute; -import org.apache.struts2.dispatcher.mapper.ActionMapper; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.dispatcher.mapper.ActionMapping; - -import com.opensymphony.xwork2.util.ValueStack; -import com.opensymphony.xwork2.inject.Inject; +import org.apache.struts2.views.annotations.StrutsTagAttribute; /** * FormButton. */ public abstract class FormButton extends ClosingUIBean { - static final String BUTTONTYPE_INPUT = "input"; - static final String BUTTONTYPE_BUTTON = "button"; - static final String BUTTONTYPE_IMAGE = "image"; + private static final String BUTTON_TYPE_INPUT = "input"; + private static final String BUTTON_TYPE_BUTTON = "button"; + private static final String BUTTON_TYPE_IMAGE = "image"; protected String action; protected String method; @@ -52,9 +45,8 @@ public FormButton(ValueStack stack, HttpServletRequest request, HttpServletRespo public void evaluateExtraParams() { super.evaluateExtraParams(); - String submitType = BUTTONTYPE_INPUT; - if (type != null && (BUTTONTYPE_BUTTON.equalsIgnoreCase(type) || (supportsImageType() && BUTTONTYPE_IMAGE.equalsIgnoreCase(type)))) - { + String submitType = BUTTON_TYPE_INPUT; + if (type != null && (BUTTON_TYPE_BUTTON.equalsIgnoreCase(type) || (supportsImageType() && BUTTON_TYPE_IMAGE.equalsIgnoreCase(type)))) { submitType = type; } @@ -62,8 +54,8 @@ public void evaluateExtraParams() { addParameter("type", submitType); - if (!BUTTONTYPE_INPUT.equals(submitType) && (label == null)) { - addParameter("label", getParameters().get("nameValue")); + if (!BUTTON_TYPE_INPUT.equals(submitType) && (label == null)) { + addParameter("label", getAttributes().get("nameValue")); } if (action != null || method != null) { @@ -101,33 +93,33 @@ public void evaluateExtraParams() { * */ protected void populateComponentHtmlId(Form form) { - String _tmp_id = ""; + String tmpId = ""; if (id != null) { // this check is needed for backwards compatibility with 2.1.x - _tmp_id = findStringIfAltSyntax(id); - } - else { - if (form != null && form.getParameters().get("id") != null) { - _tmp_id = _tmp_id + form.getParameters().get("id").toString() + "_"; + tmpId = findString(id); + } else { + if (form != null && form.getAttributes().get("id") != null) { + tmpId = tmpId + form.getAttributes().get("id").toString() + "_"; } if (name != null) { - _tmp_id = _tmp_id + escape(name); - } else if (action != null || method != null){ + tmpId = tmpId + escape(findString(name)); + } else if (action != null || method != null) { if (action != null) { - _tmp_id = _tmp_id + escape(action); + tmpId = tmpId + escape(findString(action)); } if (method != null) { - _tmp_id = _tmp_id + "_" + escape(method); + tmpId = tmpId + "_" + escape(findString(method)); } } else { // if form is null, this component is used, without a form, i guess // there's not much we could do then. if (form != null) { - _tmp_id = _tmp_id + form.getSequence(); + tmpId = tmpId + form.getSequence(); } } } - addParameter("id", _tmp_id); + addParameter("id", tmpId); + addParameter("escapedId", escape(tmpId)); } /** @@ -137,24 +129,19 @@ protected void populateComponentHtmlId(Form form) { */ protected abstract boolean supportsImageType(); - @Inject - public void setActionMapper(ActionMapper mapper) { - this.actionMapper = mapper; - } - - @StrutsTagAttribute(description="Set action attribute.") + @StrutsTagAttribute(description = "Set action attribute.") public void setAction(String action) { this.action = action; } - @StrutsTagAttribute(description="Set method attribute.") + @StrutsTagAttribute(description = "Set method attribute.") public void setMethod(String method) { this.method = method; } - @StrutsTagAttribute(description="The type of submit to use. Valid values are input, " + - "button and image.", defaultValue="input") + @StrutsTagAttribute(description = "The type of submit to use. Valid values are input, " + + "button and image.", defaultValue = "input") public void setType(String type) { this.type = type; } diff --git a/core/src/main/java/org/apache/struts2/components/GenericUIBean.java b/core/src/main/java/org/apache/struts2/components/GenericUIBean.java index 0ba693ee79..07f2f8c03e 100644 --- a/core/src/main/java/org/apache/struts2/components/GenericUIBean.java +++ b/core/src/main/java/org/apache/struts2/components/GenericUIBean.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.util.ContainUtil; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; /** * @@ -37,23 +34,23 @@ *

      * *

      Freemarker:

      - *
      Objects provided can be retrieve from within the template via $parameters._paramname_.
      + *
      Objects provided can be retrieve from within the template via $attributes._attrname_.
      * *

      JSP:

      - *
      Objects provided can be retrieve from within the template via <s:property value="%{parameters._paramname_}" />
      + *
      Objects provided can be retrieve from within the template via <s:property value="%{attributes._attrname_}" />
      * *

      - * In the bottom JSP and Velocity samples, two parameters are being passed in to the component. From within the + * In the bottom JSP and Velocity samples, two attributes are being passed in to the component. From within the * component, they can be accessed as: *

      * *

      Freemarker:

      - *
      $parameters.get('key1') and $parameters.get('key2') or $parameters.key1 and $parameters.key2
      + *
      $attributes.get('key1') and $attributes.get('key2') or $attributes.key1 and $attributes.key2
      * *

      JSP:

      *
      - * <s:property value="%{parameters.key1}" /> and <s:property value="%{'parameters.key2'}" /> or
      - * <s:property value="%{parameters.get('key1')}" /> and <s:property value="%{parameters.get('key2')}" />
      + * <s:property value="%{attributes.key1}" /> and <s:property value="%{'attributes.key2'}" /> or
      + * <s:property value="%{attributes.get('key1')}" /> and <s:property value="%{attributes.get('key2')}" />
        * 
      * *

      @@ -137,6 +134,7 @@ public boolean contains(Object obj1, Object obj2) { return ContainUtil.contains(obj1, obj2); } + @Override protected String getDefaultTemplate() { return TEMPLATE; } diff --git a/core/src/main/java/org/apache/struts2/components/Head.java b/core/src/main/java/org/apache/struts2/components/Head.java index 2cc4710a34..bd89baee63 100644 --- a/core/src/main/java/org/apache/struts2/components/Head.java +++ b/core/src/main/java/org/apache/struts2/components/Head.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; import org.apache.struts2.StrutsConstants; import org.apache.struts2.views.annotations.StrutsTag; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** * diff --git a/core/src/main/java/org/apache/struts2/components/Hidden.java b/core/src/main/java/org/apache/struts2/components/Hidden.java index 9a85d90673..b8c16237e7 100644 --- a/core/src/main/java/org/apache/struts2/components/Hidden.java +++ b/core/src/main/java/org/apache/struts2/components/Hidden.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,15 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.views.annotations.StrutsTag; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; /** * diff --git a/core/src/main/java/org/apache/struts2/components/I18n.java b/core/src/main/java/org/apache/struts2/components/I18n.java index 89e38bb886..64e002a361 100644 --- a/core/src/main/java/org/apache/struts2/components/I18n.java +++ b/core/src/main/java/org/apache/struts2/components/I18n.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,24 +16,22 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; import java.io.Writer; import java.util.ResourceBundle; -import com.opensymphony.xwork2.LocaleProviderFactory; +import org.apache.struts2.locale.LocaleProviderFactory; +import org.apache.struts2.text.LocalizedTextProvider; +import org.apache.struts2.text.TextProviderFactory; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; import org.apache.struts2.StrutsException; -import com.opensymphony.xwork2.LocaleProvider; -import com.opensymphony.xwork2.TextProvider; -import com.opensymphony.xwork2.TextProviderFactory; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.DefaultLocalizedTextProvider; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.locale.LocaleProvider; +import org.apache.struts2.text.TextProvider; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -90,28 +86,35 @@ public class I18n extends Component { protected boolean pushed; protected String name; - protected Container container; + + private LocalizedTextProvider localizedTextProvider; private TextProvider textProvider; private TextProvider defaultTextProvider; - private LocaleProvider localeProvider; + private LocaleProviderFactory localeProviderFactory; + private TextProviderFactory textProviderFactory; public I18n(ValueStack stack) { super(stack); } - + @Inject - public void setContainer(Container container) { - this.container = container; + public void setLocalizedTextProvider(LocalizedTextProvider localizedTextProvider) { + this.localizedTextProvider = localizedTextProvider; } - @Inject + @Inject("system") public void setTextProvider(TextProvider textProvider) { this.defaultTextProvider = textProvider; } + @Inject + public void setTextProviderFactory(TextProviderFactory textProviderFactory) { + this.textProviderFactory = textProviderFactory; + } + @Inject public void setLocaleProviderFactory(LocaleProviderFactory localeProviderFactory) { - this.localeProvider = localeProviderFactory.createLocaleProvider(); + this.localeProviderFactory = localeProviderFactory; } public boolean start(Writer writer) { @@ -122,12 +125,12 @@ public boolean start(Writer writer) { ResourceBundle bundle = defaultTextProvider.getTexts(name); if (bundle == null) { - bundle = container.getInstance(DefaultLocalizedTextProvider.class).findResourceBundle(name, localeProvider.getLocale()); + LocaleProvider localeProvider = localeProviderFactory.createLocaleProvider(); + bundle = localizedTextProvider.findResourceBundle(name, localeProvider.getLocale()); } if (bundle != null) { - TextProviderFactory tpf = container.inject(TextProviderFactory.class); - textProvider = tpf.createInstance(bundle); + textProvider = textProviderFactory.createInstance(bundle); getStack().push(textProvider); pushed = true; } diff --git a/core/src/main/java/org/apache/struts2/components/If.java b/core/src/main/java/org/apache/struts2/components/If.java index d9a81155ae..19ecf528ae 100644 --- a/core/src/main/java/org/apache/struts2/components/If.java +++ b/core/src/main/java/org/apache/struts2/components/If.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,15 +16,13 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import java.io.Writer; - +import org.apache.struts2.util.ValueStack; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import com.opensymphony.xwork2.util.ValueStack; +import java.io.Writer; /** * @@ -89,7 +85,7 @@ public boolean start(Writer writer) { answer = Boolean.FALSE; } stack.getContext().put(ANSWER, answer); - return answer.booleanValue(); + return answer; } public boolean end(Writer writer, String body) { diff --git a/core/src/main/java/org/apache/struts2/components/Include.java b/core/src/main/java/org/apache/struts2/components/Include.java index 36f0a87589..f8decac25f 100644 --- a/core/src/main/java/org/apache/struts2/components/Include.java +++ b/core/src/main/java/org/apache/struts2/components/Include.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,29 +16,39 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.RequestDispatcher; +import jakarta.servlet.ServletException; +import jakarta.servlet.ServletOutputStream; +import jakarta.servlet.ServletRequest; +import jakarta.servlet.WriteListener; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletResponseWrapper; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.RequestUtils; import org.apache.struts2.StrutsConstants; +import org.apache.struts2.StrutsException; import org.apache.struts2.util.FastByteArrayOutputStream; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.RequestDispatcher; -import javax.servlet.ServletException; -import javax.servlet.ServletOutputStream; -import javax.servlet.ServletRequest; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpServletResponseWrapper; -import java.io.*; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.PrintWriter; +import java.io.Writer; import java.net.URLEncoder; -import java.util.*; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.Stack; +import java.util.StringTokenizer; /** * @@ -93,12 +101,13 @@ public class Include extends Component { private static final Logger LOG = LogManager.getLogger(Include.class); - private static String systemEncoding = System.getProperty("file.encoding"); + private static final String SYSTEM_ENCODING = Charset.defaultCharset().displayName(); protected String value; - private HttpServletRequest req; - private HttpServletResponse res; - private static String defaultEncoding; + private final HttpServletRequest req; + private final HttpServletResponse res; + private String defaultEncoding; // Made non-static (during WW-4971 fix) + private boolean useResponseEncoding = true; // Added with WW-4971 fix (allows switch between usage of response or default encoding) public Include(ValueStack stack, HttpServletRequest req, HttpServletResponse res) { super(stack); @@ -111,22 +120,37 @@ public void setDefaultEncoding(String encoding) { defaultEncoding = encoding; } + @Inject(value = StrutsConstants.STRUTS_TAG_INCLUDETAG_USERESPONSEENCODING, required=false) + public void setUseResponseEncoding(String useEncoding) { + useResponseEncoding = Boolean.parseBoolean(useEncoding); + } + public boolean end(Writer writer, String body) { String page = findString(value, "value", "You must specify the URL to include. Example: /foo.jsp"); StringBuilder urlBuf = new StringBuilder(); + String encodingForInclude; + + if (useResponseEncoding) { + encodingForInclude = res.getCharacterEncoding(); // Use response (page) encoding + if (encodingForInclude == null || encodingForInclude.isEmpty()) { + encodingForInclude = defaultEncoding; // Revert to defaultEncoding when response (page) encoding is invalid + } + } + else { + encodingForInclude = defaultEncoding; // Use default encoding (when useResponseEncoding is false) + } // Add URL urlBuf.append(page); // Add request parameters - if (parameters.size() > 0) { + if (!attributes.isEmpty()) { urlBuf.append('?'); String concat = ""; // Set parameters - for (Object next : parameters.entrySet()) { - Map.Entry entry = (Map.Entry) next; + for (Map.Entry entry : attributes.entrySet()) { Object name = entry.getKey(); List values = (List) entry.getValue(); @@ -135,11 +159,7 @@ public boolean end(Writer writer, String body) { urlBuf.append(name); urlBuf.append('='); - try { - urlBuf.append(URLEncoder.encode(value.toString(), "UTF-8")); - } catch (UnsupportedEncodingException e) { - LOG.warn("Unable to url-encode {}, it will be ignored", value); - } + urlBuf.append(URLEncoder.encode(value.toString(), StandardCharsets.UTF_8)); concat = "&"; } @@ -150,7 +170,7 @@ public boolean end(Writer writer, String body) { // Include try { - include(result, writer, req, res, defaultEncoding); + include(result, writer, req, res, encodingForInclude); } catch (ServletException | IOException e) { LOG.warn("Exception thrown during include of {}", result, e); } @@ -168,11 +188,10 @@ public static String getContextRelativePath(ServletRequest request, String relat if (relativePath.startsWith("/")) { returnValue = relativePath; - } else if (!(request instanceof HttpServletRequest)) { + } else if (!(request instanceof HttpServletRequest hrequest)) { returnValue = relativePath; } else { - HttpServletRequest hrequest = (HttpServletRequest) request; - String uri = (String) request.getAttribute("javax.servlet.include.servlet_path"); + String uri = (String) request.getAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH); if (uri == null) { uri = RequestUtils.getServletPath(hrequest); @@ -184,7 +203,7 @@ public static String getContextRelativePath(ServletRequest request, String relat // .. is illegal in an absolute path according to the Servlet Spec and will cause // known problems on Orion application servers. if (returnValue.contains("..")) { - Stack stack = new Stack(); + Stack stack = new Stack<>(); StringTokenizer pathParts = new StringTokenizer(returnValue.replace('\\', '/'), "/"); while (pathParts.hasMoreTokens()) { @@ -212,15 +231,15 @@ public static String getContextRelativePath(ServletRequest request, String relat } public void addParameter(String key, Object value) { - // don't use the default implementation of addParameter, + // Don't use the default implementation of addParameter, // instead, include tag requires that each parameter be a list of objects, // just like the HTTP servlet interfaces are (String[]) if (value != null) { - List currentValues = (List) parameters.get(key); + List currentValues = (List) attributes.get(key); if (currentValues == null) { currentValues = new ArrayList(); - parameters.put(key, currentValues); + attributes.put(key, currentValues); } currentValues.add(value); @@ -230,7 +249,7 @@ public void addParameter(String key, Object value) { /** * Include a resource in a response. * - * @param relativePath the relative path of the resource to include; resolves to {@link #getContextRelativePath(javax.servlet.ServletRequest, + * @param relativePath the relative path of the resource to include; resolves to {@link #getContextRelativePath(jakarta.servlet.ServletRequest, * String)} * @param writer the Writer to write output to * @param request the current request @@ -259,8 +278,8 @@ public static void include( String relativePath, Writer writer, ServletRequest r // Use given encoding pageResponse.getContent().writeTo(writer, encoding); } else { - //use the platform specific encoding - pageResponse.getContent().writeTo(writer, systemEncoding); + // Use the platform specific encoding + pageResponse.getContent().writeTo(writer, SYSTEM_ENCODING); } } @@ -273,13 +292,26 @@ public static void include( String relativePath, Writer writer, ServletRequest r */ static final class PageOutputStream extends ServletOutputStream { - private FastByteArrayOutputStream buffer; + private final FastByteArrayOutputStream buffer; public PageOutputStream() { buffer = new FastByteArrayOutputStream(); } + @Override + public boolean isReady() { + return true; + } + + @Override + public void setWriteListener(WriteListener writeListener) { + try { + writeListener.onWritePossible(); + } catch (IOException e) { + throw new StrutsException(e); + } + } /** * Return all data that has been written to this OutputStream. @@ -290,22 +322,27 @@ public FastByteArrayOutputStream getBuffer() throws IOException { return buffer; } + @Override public void close() throws IOException { buffer.close(); } + @Override public void flush() throws IOException { buffer.flush(); } + @Override public void write(byte[] b, int o, int l) throws IOException { buffer.write(b, o, l); } + @Override public void write(int i) throws IOException { buffer.write(i); } + @Override public void write(byte[] b) throws IOException { buffer.write(b); } @@ -332,8 +369,7 @@ public void write(byte[] b) throws IOException { */ static final class PageResponse extends HttpServletResponseWrapper { - protected PrintWriter pagePrintWriter; - protected ServletOutputStream outputStream; + private PrintWriter pagePrintWriter; private PageOutputStream pageOutputStream = null; @@ -344,7 +380,6 @@ public PageResponse(HttpServletResponse response) { super(response); } - /** * Return the content buffered inside the {@link PageOutputStream}. * @@ -352,9 +387,9 @@ public PageResponse(HttpServletResponse response) { * @throws IOException */ public FastByteArrayOutputStream getContent() throws IOException { - //if we are using a writer, we need to flush the - //data to the underlying outputstream. - //most containers do this - but it seems Jetty 4.0.5 doesn't + // If we are using a writer, we need to flush the + // data to the underlying outputstream. + // Most containers do this - but it seems Jetty 4.0.5 doesn't if (pagePrintWriter != null) { pagePrintWriter.flush(); } @@ -366,6 +401,7 @@ public FastByteArrayOutputStream getContent() throws IOException { * Return instance of {@link PageOutputStream} * allowing all data written to stream to be stored in temporary buffer. */ + @Override public ServletOutputStream getOutputStream() throws IOException { if (pageOutputStream == null) { pageOutputStream = new PageOutputStream(); @@ -377,6 +413,7 @@ public ServletOutputStream getOutputStream() throws IOException { /** * Return PrintWriter wrapper around PageOutputStream. */ + @Override public PrintWriter getWriter() throws IOException { if (pagePrintWriter == null) { pagePrintWriter = new PrintWriter(new OutputStreamWriter(getOutputStream(), getCharacterEncoding())); diff --git a/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java b/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java index c4012004d1..8692daf943 100644 --- a/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java +++ b/core/src/main/java/org/apache/struts2/components/InputTransferSelect.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,18 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.util.LinkedHashMap; import java.util.Map; @@ -177,7 +174,7 @@ public void evaluateExtraParams() { // key -> select tag id, value -> headerKey (if exists) - Map formInputtransferselectIds = (Map) formAncestor.getParameters().get("inputtransferselectIds"); + Map formInputtransferselectIds = (Map) formAncestor.getAttributes().get("inputtransferselectIds"); // init lists if (formInputtransferselectIds == null) { @@ -185,18 +182,18 @@ public void evaluateExtraParams() { } // id - String tmpId = (String) getParameters().get("id"); - String tmpHeaderKey = (String) getParameters().get("headerKey"); + String tmpId = (String) getAttributes().get("id"); + String tmpHeaderKey = (String) getAttributes().get("headerKey"); if (tmpId != null && (! formInputtransferselectIds.containsKey(tmpId))) { formInputtransferselectIds.put(tmpId, tmpHeaderKey); } - formAncestor.getParameters().put("inputtransferselectIds", formInputtransferselectIds); + formAncestor.getAttributes().put("inputtransferselectIds", formInputtransferselectIds); } else { if (LOG.isWarnEnabled()) { - LOG.warn("form enclosing inputtransferselect "+this+" not found, auto select upon form submit of inputtransferselect will not work"); + LOG.warn("form enclosing inputtransferselect {} not found, auto select upon form submit of inputtransferselect will not work", this); } } } diff --git a/core/src/main/java/org/apache/struts2/components/IteratorComponent.java b/core/src/main/java/org/apache/struts2/components/IteratorComponent.java index 1474fe9848..c31f024868 100644 --- a/core/src/main/java/org/apache/struts2/components/IteratorComponent.java +++ b/core/src/main/java/org/apache/struts2/components/IteratorComponent.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,13 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.ognl.ThreadAllowlist; import org.apache.struts2.util.MakeIterator; +import org.apache.struts2.util.ValueStack; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; import org.apache.struts2.views.jsp.IteratorStatus; @@ -191,8 +190,8 @@ * * *

      Another way to create a simple loop, similar to JSTL's - * <c:forEach begin="..." end="..." ...> is to use some - * OGNL magic, which provides some under-the-covers magic to + * <c:forEach begin="..." end="..." ...> is to use some + * OGNL magic, which provides some under-the-covers magic to * make 0-n loops trivial. This example also loops five times.

      * * @@ -240,11 +239,17 @@ public class IteratorComponent extends ContextBean { protected Integer end; protected String stepStr; protected Integer step; + private ThreadAllowlist threadAllowlist; public IteratorComponent(ValueStack stack) { super(stack); } + @Inject + public void setThreadAllowlist(ThreadAllowlist threadAllowlist) { + this.threadAllowlist = threadAllowlist; + } + public boolean start(Writer writer) { //Create an iterator status if the status attribute was set. if (statusAttr != null) { @@ -284,8 +289,7 @@ public boolean start(Writer writer) { if (end == null) end = step > 0 ? values.length - 1 : 0; iterator = new CounterIterator(begin, end, step, Arrays.asList(values)); - } else if (iteratorTarget instanceof List) { - List values = (List) iteratorTarget; + } else if (iteratorTarget instanceof List values) { if (end == null) end = step > 0 ? values.size() - 1 : 0; iterator = new CounterIterator(begin, end, step, values); @@ -302,6 +306,10 @@ public boolean start(Writer writer) { Object currentValue = iterator.next(); stack.push(currentValue); + if (currentValue != null) { + threadAllowlist.allowClassHierarchy(currentValue.getClass()); + } + String var = getVar(); if ((var != null)) { @@ -357,9 +365,9 @@ public boolean end(Writer writer, String body) { static class CounterIterator implements Iterator { private int step; - private int end; + private final int end; private int currentIndex; - private List values; + private final List values; CounterIterator(Integer begin, Integer end, Integer step, List values) { this.end = end; @@ -369,11 +377,13 @@ static class CounterIterator implements Iterator { this.values = values; } + @Override public boolean hasNext() { int next = peekNextIndex(); return step > 0 ? next <= end : next >= end; } + @Override public Object next() { if (hasNext()) { int nextIndex = peekNextIndex(); @@ -388,6 +398,7 @@ private int peekNextIndex() { return currentIndex + step; } + @Override public void remove() { throw new UnsupportedOperationException("Values cannot be removed from this iterator"); } diff --git a/core/src/main/java/org/apache/struts2/components/Label.java b/core/src/main/java/org/apache/struts2/components/Label.java index 644b38951d..52ba02ac79 100644 --- a/core/src/main/java/org/apache/struts2/components/Label.java +++ b/core/src/main/java/org/apache/struts2/components/Label.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,17 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.struts2.util.TextProviderHelper; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import org.apache.struts2.util.TextProviderHelper; - -import com.opensymphony.xwork2.util.ValueStack; /** * @@ -84,14 +79,14 @@ protected void evaluateExtraParams() { if (value != null) { addParameter("nameValue", findString(value)); } else if (key != null) { - Object nameValue = parameters.get("nameValue"); - if (nameValue == null || nameValue.toString().length() == 0) { + Object nameValue = attributes.get("nameValue"); + if (nameValue == null || nameValue.toString().isEmpty()) { // get the label from a TextProvider (default value is the key) String providedLabel = TextProviderHelper.getText(key, key, stack); addParameter("nameValue", providedLabel); } } else if (name != null) { - String expr = completeExpressionIfAltSyntax(name); + String expr = completeExpression(name); addParameter("nameValue", findString(expr)); } } diff --git a/core/src/main/java/org/apache/struts2/components/Link.java b/core/src/main/java/org/apache/struts2/components/Link.java new file mode 100644 index 0000000000..5c29765f73 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/components/Link.java @@ -0,0 +1,170 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +package org.apache.struts2.components; + +import org.apache.struts2.util.ValueStack; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + +/** + *

      + * Add nonce propagation feature to implement CSP in link tags + *

      + * + *

      + * The link tag allows the user to load external resources, most usually style sheets. External resources + * can inject malicious code and perform XSS and data injection attacks. The s:link tag includes a nonce + * attribute that is being randomly generated with each request and only allows links with the valid + * nonce value to be executed. + *

      + * + *

      Examples

      + * + *
      + *
      + * <s:link ... />
      + *
      + * 
      + * + */ +@StrutsTag(name="link", + tldTagClass="org.apache.struts2.views.jsp.ui.LinkTag", + description="Link tag automatically adds nonces to link elements - should be used in combination with Struts' CSP Interceptor.", + allowDynamicAttributes=true) +public class Link extends UIBean{ + + private static final String TEMPLATE="link"; + + protected String href; + protected String hreflang; + protected String rel; + protected String media; + protected String referrerpolicy; + protected String sizes; + protected String crossorigin; + protected String type; + protected String as; + + public Link(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + @StrutsTagAttribute(description="HTML link href attribute") + public void setHref(String href) { + this.href = href; + } + + @StrutsTagAttribute(description="HTML link hreflang attribute") + public void setHreflang(String hreflang) { + this.hreflang = hreflang; + } + + @StrutsTagAttribute(description="HTML link rel attribute") + public void setRel(String rel) { + this.rel = rel; + } + + @StrutsTagAttribute(description="HTML link sizes attribute") + public void setSizes(String sizes) { + this.sizes = sizes; + } + + @StrutsTagAttribute(description="HTML link crossorigin attribute") + public void setCrossorigin(String crossorigin) { + this.crossorigin = crossorigin; + } + + @StrutsTagAttribute(description="HTML link type attribute") + public void setType(String type) { + this.type = type; + } + + @StrutsTagAttribute(description="HTML link as attribute") + public void setAs(String as) { + this.as = as; + } + + @StrutsTagAttribute(description="HTML link media attribute") + public void setMedia(String media) { + this.media = media; + } + + @StrutsTagAttribute(description="HTML link referrerpolicy attribute") + public void setReferrerpolicy(String referrerpolicy) { + this.referrerpolicy = referrerpolicy; + } + + @Override + protected String getDefaultTemplate() { + return TEMPLATE; + } + + @Override + protected void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (href != null) { + addParameter("href", findString(href)); + } + + if (hreflang != null) { + addParameter("hreflang", findString(hreflang)); + } + + if (rel != null) { + addParameter("rel", findString(rel)); + } + + if (media != null) { + addParameter("media", findString(media)); + } + + if (referrerpolicy != null) { + addParameter("referrerpolicy", findString(referrerpolicy)); + } + + if (sizes != null) { + addParameter("sizes", findString(sizes)); + } + + if (crossorigin != null) { + addParameter("crossorigin", findString(crossorigin)); + } + + if (type != null) { + addParameter("type", findString(type)); + } + + if (as != null) { + addParameter("as", findString(as)); + } + + if (disabled != null) { + addParameter("disabled", findString(disabled)); + } + + if (title != null) { + addParameter("title", findString(title)); + } + } +} diff --git a/core/src/main/java/org/apache/struts2/components/ListUIBean.java b/core/src/main/java/org/apache/struts2/components/ListUIBean.java index 75b29f0d05..b5b11f053b 100644 --- a/core/src/main/java/org/apache/struts2/components/ListUIBean.java +++ b/core/src/main/java/org/apache/struts2/components/ListUIBean.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,19 +16,19 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.commons.lang3.StringUtils; import org.apache.struts2.util.ContainUtil; import org.apache.struts2.util.MakeIterator; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import java.lang.reflect.Array; import java.util.Collection; +import java.util.Collections; import java.util.Map; /** @@ -64,37 +62,38 @@ protected ListUIBean(ValueStack stack, HttpServletRequest request, HttpServletRe super(stack, request, response); } + @Override public void evaluateExtraParams() { - Object value = null; + Object value; if (list == null) { - list = parameters.get("list"); + list = attributes.get("list"); } if (list instanceof String) { value = findValue((String) list); - } else if (list instanceof Collection) { - value = list; - } else if (MakeIterator.isIterable(list)) { - value = MakeIterator.convert(list); - } - if (value == null) { - if (throwExceptionOnNullValueAttribute) { - // will throw an exception if not found - value = findValue((list == null) ? (String) list : list.toString(), "list", - "The requested list key '" + list + "' could not be resolved as a collection/array/map/enumeration/iterator type. " + - "Example: people or people.{name}"); - } else { - // ww-1010, allows value with null value to be compatible with ww - // 2.1.7 behaviour - value = findValue((list == null) ? (String) list : list.toString()); + if (value == null) { + if (throwExceptionOnNullValueAttribute) { + // will throw an exception if not found + value = findValue(list == null ? null : list.toString(), "list", + "The requested list key '" + list + "' could not be resolved as a collection/array/map/enumeration/iterator type. " + + "Example: people or people.{name}"); + } else { + // ww-1010, allows value with null value to be compatible with ww + // 2.1.7 behaviour + value = findValue(list == null ? null : list.toString()); + } } + } else { + value = list; } - if (value instanceof Collection) { + if (value == null || value instanceof Iterable) { addParameter("list", value); - } else { + } else if (MakeIterator.isIterable(value)) { addParameter("list", MakeIterator.convert(value)); + } else { + addParameter("list", Collections.singletonList(value)); } if (value instanceof Collection) { @@ -106,26 +105,30 @@ public void evaluateExtraParams() { } if (listKey != null) { - listKey = stripExpressionIfAltSyntax(listKey); + listKey = stripExpression(listKey); addParameter("listKey", listKey); } else if (value instanceof Map) { addParameter("listKey", "key"); + } else { + addParameter("listKey", "top"); } if (listValueKey != null) { - listValueKey = stripExpressionIfAltSyntax(listValueKey); + listValueKey = stripExpression(listValueKey); addParameter("listValueKey", listValueKey); } if (listValue != null) { - listValue = stripExpressionIfAltSyntax(listValue); + listValue = stripExpression(listValue); addParameter("listValue", listValue); } else if (value instanceof Map) { addParameter("listValue", "value"); + } else { + addParameter("listValue", "top"); } if (listLabelKey != null) { - listLabelKey = stripExpressionIfAltSyntax(listLabelKey); + listLabelKey = stripExpression(listLabelKey); addParameter("listLabelKey", listLabelKey); } @@ -146,6 +149,7 @@ public boolean contains(Object obj1, Object obj2) { return ContainUtil.contains(obj1, obj2); } + @Override protected Class getValueClassType() { return null; // don't convert nameValue to anything, we need the raw value } @@ -191,7 +195,6 @@ public void setListTitle(String listTitle) { this.listTitle = listTitle; } - public void setThrowExceptionOnNullValueAttribute(boolean throwExceptionOnNullValueAttribute) { this.throwExceptionOnNullValueAttribute = throwExceptionOnNullValueAttribute; } diff --git a/core/src/main/java/org/apache/struts2/components/MergeIterator.java b/core/src/main/java/org/apache/struts2/components/MergeIterator.java index faeb62c3d5..2a5270b443 100644 --- a/core/src/main/java/org/apache/struts2/components/MergeIterator.java +++ b/core/src/main/java/org/apache/struts2/components/MergeIterator.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.components.Param.UnnamedParametric; @@ -58,56 +55,56 @@ *
    • Display third element of the thrid list
    • * * - * + *

      * *

        *
      • var (String) - the name where the resultant merged iterator will be stored in the stack's context
      • *
      * - * - * + *

      + *

      * * public class MergeIteratorTagAction extends ActionSupport { - * + *

      * private List myList1; * private List myList2; * private List myList3; - * + *

      * public List getMyList1() { * return myList1; * } - * + *

      * public List getMyList2() { * return myList2; * } - * + *

      * public List getMyList3() { * return myList3; * } - * - * + *

      + *

      * public String execute() throws Exception { - * + *

      * myList1 = new ArrayList(); * myList1.add("1"); * myList1.add("2"); * myList1.add("3"); - * + *

      * myList2 = new ArrayList(); * myList2.add("a"); * myList2.add("b"); * myList2.add("c"); - * + *

      * myList3 = new ArrayList(); * myList3.add("A"); * myList3.add("B"); * myList3.add("C"); - * + *

      * return "done"; * } * } * - * + *

      * * <s:merge var="myMergedIterator1"> * <s:param value="%{myList1}" /> @@ -118,23 +115,22 @@ * <s:property /> * </s:iterator> * - * + *

      * * This wil generate "1aA2bB3cC". * * * @see org.apache.struts2.util.MergeIteratorFilter * @see org.apache.struts2.views.jsp.iterator.MergeIteratorTag - * */ -@StrutsTag(name="merge", tldTagClass="org.apache.struts2.views.jsp.iterator.MergeIteratorTag", description="Merge the values " + - "of a list of iterators into one iterator") +@StrutsTag(name = "merge", tldTagClass = "org.apache.struts2.views.jsp.iterator.MergeIteratorTag", + description = "Merge the values of a list of iterators into one iterator") public class MergeIterator extends ContextBean implements UnnamedParametric { private static final Logger LOG = LogManager.getLogger(MergeIterator.class); private MergeIteratorFilter mergeIteratorFilter = null; - private List _parameters; + private List attributesToMerge; public MergeIterator(ValueStack stack) { super(stack); @@ -143,15 +139,14 @@ public MergeIterator(ValueStack stack) { public boolean start(Writer writer) { mergeIteratorFilter = new MergeIteratorFilter(); - _parameters = new ArrayList(); + attributesToMerge = new ArrayList<>(); return super.start(writer); } public boolean end(Writer writer, String body) { - - for (Object iteratorEntryObj : _parameters) { - if (! MakeIterator.isIterable(iteratorEntryObj)) { + for (Object iteratorEntryObj : attributesToMerge) { + if (!MakeIterator.isIterable(iteratorEntryObj)) { LOG.warn("param with value resolved as {} cannot be make as iterator, it will be ignored and hence will not appear in the merged iterator", iteratorEntryObj); continue; } @@ -168,13 +163,12 @@ public boolean end(Writer writer, String body) { return super.end(writer, body); } - @StrutsTagAttribute(description="The name where the resultant merged iterator will be stored in the stack's context") + @StrutsTagAttribute(description = "The name where the resultant merged iterator will be stored in the stack's context") public void setVar(String var) { super.setVar(var); } - // == UnnamedParametric interface implementation --------------------- public void addParameter(Object value) { - _parameters.add(value); + attributesToMerge.add(value); } } diff --git a/core/src/main/java/org/apache/struts2/components/Number.java b/core/src/main/java/org/apache/struts2/components/Number.java index 7ca45b14c2..db101faff4 100644 --- a/core/src/main/java/org/apache/struts2/components/Number.java +++ b/core/src/main/java/org/apache/struts2/components/Number.java @@ -18,10 +18,10 @@ */ package org.apache.struts2.components; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.util.ValueStack; -import org.apache.logging.log4j.Logger; +import org.apache.struts2.ActionContext; +import org.apache.struts2.util.ValueStack; import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; @@ -172,7 +172,7 @@ private void findCurrency(NumberFormat format) { try { format.setCurrency(Currency.getInstance(currency)); } catch (IllegalArgumentException iae) { - LOG.error("Could not recognise a currency of [" + currency + "]"); + LOG.error("Could not recognise a currency of [{}]", currency); } } } @@ -208,7 +208,7 @@ private java.lang.Number findNumberName() { number = (java.lang.Number) numberObject; } } catch (Exception e) { - LOG.error("Could not convert object with key [" + name + "] to a java.lang.Number instance"); + LOG.error("Could not convert object with key [{}] to a java.lang.Number instance", name); } return number; } @@ -233,7 +233,7 @@ private void setRoundingMode(NumberFormat format) { } else if ("up".equals(roundingMode)) { format.setRoundingMode(RoundingMode.UP); } else { - LOG.error("Could not recognise a roundingMode of [" + roundingMode + "]"); + LOG.error("Could not recognise a roundingMode of [{}]", roundingMode); } } } diff --git a/core/src/main/java/org/apache/struts2/components/OptGroup.java b/core/src/main/java/org/apache/struts2/components/OptGroup.java index 1be09e0ab8..0472c73ab9 100644 --- a/core/src/main/java/org/apache/struts2/components/OptGroup.java +++ b/core/src/main/java/org/apache/struts2/components/OptGroup.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,24 +16,21 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import java.io.Writer; -import java.util.ArrayList; -import java.util.List; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - +import org.apache.struts2.inject.Container; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import com.opensymphony.xwork2.inject.Container; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; -import org.apache.logging.log4j.Logger; -import org.apache.logging.log4j.LogManager; +import java.io.Writer; +import java.util.ArrayList; +import java.util.List; /** * @@ -76,7 +71,7 @@ public class OptGroup extends Component { public static final String INTERNAL_LIST_UI_BEAN_LIST_PARAMETER_KEY = "optGroupInternalListUiBeanList"; - private static Logger LOG = LogManager.getLogger(OptGroup.class); + private static final Logger LOG = LogManager.getLogger(OptGroup.class); protected HttpServletRequest req; protected HttpServletResponse res; @@ -93,7 +88,7 @@ protected String getDefaultTemplate() { } }; } - + @Inject public void setContainer(Container container) { container.inject(internalUiBean); @@ -109,7 +104,7 @@ public boolean end(Writer writer, String body) { internalUiBean.start(writer); internalUiBean.end(writer, body); - List listUiBeans = (List) select.getParameters().get(INTERNAL_LIST_UI_BEAN_LIST_PARAMETER_KEY); + List listUiBeans = (List) select.getAttributes().get(INTERNAL_LIST_UI_BEAN_LIST_PARAMETER_KEY); if (listUiBeans == null) { listUiBeans = new ArrayList(); } @@ -130,7 +125,7 @@ public void setDisabled(String disabled) { } @StrutsTagAttribute(description="Set the list attribute.") - public void setList(String list) { + public void setList(Object list) { internalUiBean.setList(list); } @@ -143,4 +138,19 @@ public void setListKey(String listKey) { public void setListValue(String listValue) { internalUiBean.setListValue(listValue); } + + @StrutsTagAttribute(description = "Property of list objects to get css class from") + public void setListCssClass(String listCssClass) { + internalUiBean.setListCssClass(listCssClass); + } + + @StrutsTagAttribute(description = "Property of list objects to get css style from") + public void setListCssStyle(String listCssStyle) { + internalUiBean.setListCssStyle(listCssStyle); + } + + @StrutsTagAttribute(description = "Property of list objects to get title from") + public void setListTitle(String listTitle) { + internalUiBean.setListTitle(listTitle); + } } diff --git a/core/src/main/java/org/apache/struts2/components/OptionTransferSelect.java b/core/src/main/java/org/apache/struts2/components/OptionTransferSelect.java index 091dd64cc7..fc3bcd5198 100644 --- a/core/src/main/java/org/apache/struts2/components/OptionTransferSelect.java +++ b/core/src/main/java/org/apache/struts2/components/OptionTransferSelect.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,18 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.util.LinkedHashMap; import java.util.Map; @@ -140,7 +137,7 @@ protected String getDefaultTemplate() { public void evaluateExtraParams() { super.evaluateExtraParams(); - Object doubleValue = null; + Object doubleValue; // override DoubleListUIBean's if (doubleList != null) { @@ -290,8 +287,8 @@ public void evaluateExtraParams() { // key -> select tag id, value -> headerKey (if exists) - Map formOptiontransferselectIds = (Map) formAncestor.getParameters().get("optiontransferselectIds"); - Map formOptiontransferselectDoubleIds = (Map) formAncestor.getParameters().get("optiontransferselectDoubleIds"); + Map formOptiontransferselectIds = (Map) formAncestor.getAttributes().get("optiontransferselectIds"); + Map formOptiontransferselectDoubleIds = (Map) formAncestor.getAttributes().get("optiontransferselectDoubleIds"); // init lists if (formOptiontransferselectIds == null) { @@ -303,26 +300,26 @@ public void evaluateExtraParams() { // id - String tmpId = (String) getParameters().get("id"); - String tmpHeaderKey = (String) getParameters().get("headerKey"); + String tmpId = (String) getAttributes().get("id"); + String tmpHeaderKey = (String) getAttributes().get("headerKey"); if (tmpId != null && (! formOptiontransferselectIds.containsKey(tmpId))) { formOptiontransferselectIds.put(tmpId, tmpHeaderKey); } // doubleId - String tmpDoubleId = (String) getParameters().get("doubleId"); - String tmpDoubleHeaderKey = (String) getParameters().get("doubleHeaderKey"); + String tmpDoubleId = (String) getAttributes().get("doubleId"); + String tmpDoubleHeaderKey = (String) getAttributes().get("doubleHeaderKey"); if (tmpDoubleId != null && (! formOptiontransferselectDoubleIds.containsKey(tmpDoubleId))) { formOptiontransferselectDoubleIds.put(tmpDoubleId, tmpDoubleHeaderKey); } - formAncestor.getParameters().put("optiontransferselectIds", formOptiontransferselectIds); - formAncestor.getParameters().put("optiontransferselectDoubleIds", formOptiontransferselectDoubleIds); + formAncestor.getAttributes().put("optiontransferselectIds", formOptiontransferselectIds); + formAncestor.getAttributes().put("optiontransferselectDoubleIds", formOptiontransferselectDoubleIds); } else { if (LOG.isWarnEnabled()) { - LOG.warn("form enclosing optiontransferselect "+this+" not found, auto select upon form submit of optiontransferselect will not work"); + LOG.warn("form enclosing optiontransferselect {} not found, auto select upon form submit of optiontransferselect will not work", this); } } } diff --git a/core/src/main/java/org/apache/struts2/components/Param.java b/core/src/main/java/org/apache/struts2/components/Param.java index 9976d22546..6fcd70a2eb 100644 --- a/core/src/main/java/org/apache/struts2/components/Param.java +++ b/core/src/main/java/org/apache/struts2/components/Param.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,10 +16,9 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.commons.lang3.StringUtils; import org.apache.struts2.StrutsException; import org.apache.struts2.views.annotations.StrutsTag; @@ -128,23 +125,29 @@ public boolean end(Writer writer, String body) { if (component instanceof UnnamedParametric) { ((UnnamedParametric) component).addParameter(findValue(value)); } else { - String name = findString(this.name); + String translatedName = findString(this.name); - if (name == null) { + if (translatedName == null) { throw new StrutsException("No name found for following expression: " + this.name); } - Object value = findValue(this.value); + boolean evaluated = !translatedName.equals(this.name); + boolean reevaluate = !evaluated || isAcceptableExpression(translatedName); + if (!reevaluate) { + throw new StrutsException("Excluded or not accepted name found: " + translatedName); + } + + Object foundValue = findValue(this.value); if (suppressEmptyParameters) { - if (value != null && StringUtils.isNotBlank(value.toString())) { - component.addParameter(name, value); + if (foundValue != null && StringUtils.isNotBlank(foundValue.toString())) { + component.addParameter(translatedName, foundValue); } else { - component.addParameter(name, null); + component.addParameter(translatedName, null); } - } else if (value == null || StringUtils.isBlank(value.toString())) { - component.addParameter(name, ""); + } else if (foundValue == null || StringUtils.isBlank(foundValue.toString())) { + component.addParameter(translatedName, ""); } else { - component.addParameter(name, value); + component.addParameter(translatedName, foundValue); } } } else { @@ -161,7 +164,8 @@ public boolean end(Writer writer, String body) { return super.end(writer, ""); } - + + @Override public boolean usesBody() { return true; } @@ -175,12 +179,12 @@ public void setName(String name) { public void setValue(String value) { this.value = value; } - + @StrutsTagAttribute(description="Whether to suppress empty parameters", type="Boolean", defaultValue="false") public void setSuppressEmptyParameters(boolean suppressEmptyParameters) { this.suppressEmptyParameters = suppressEmptyParameters; } - + /** *

      * Tags can implement this to support nested param tags without the name attribute. @@ -196,7 +200,7 @@ public interface UnnamedParametric { * Adds the given value as a parameter to the outer tag. * @param value the value */ - public void addParameter(Object value); + void addParameter(Object value); } } diff --git a/core/src/main/java/org/apache/struts2/components/Password.java b/core/src/main/java/org/apache/struts2/components/Password.java index 3f54b29711..471f7dbd24 100644 --- a/core/src/main/java/org/apache/struts2/components/Password.java +++ b/core/src/main/java/org/apache/struts2/components/Password.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; /** * diff --git a/core/src/main/java/org/apache/struts2/components/Property.java b/core/src/main/java/org/apache/struts2/components/Property.java index 9d2c2b6d52..f57bd1cb48 100644 --- a/core/src/main/java/org/apache/struts2/components/Property.java +++ b/core/src/main/java/org/apache/struts2/components/Property.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,11 +16,10 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; -import org.apache.commons.lang3.StringEscapeUtils; +import org.apache.struts2.util.ValueStack; +import org.apache.commons.text.StringEscapeUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.views.annotations.StrutsTag; @@ -137,13 +134,13 @@ public void setEscapeXml(boolean escapeXml) { public boolean start(Writer writer) { boolean result = super.start(writer); - String actualValue = null; + String actualValue; if (value == null) { value = "top"; } else { - value = stripExpressionIfAltSyntax(value); + value = stripExpression(value); } // exception: don't call findString(), since we don't want the @@ -165,15 +162,15 @@ public boolean start(Writer writer) { } private String prepare(String value) { - String result = value; + String result = value; if (escapeHtml) { - result = StringEscapeUtils.escapeHtml4(result); + result = StringEscapeUtils.escapeHtml4(result); } if (escapeJavaScript) { - result = StringEscapeUtils.escapeEcmaScript(result); + result = StringEscapeUtils.escapeEcmaScript(result); } if (escapeXml) { - result = StringEscapeUtils.escapeXml(result); + result = StringEscapeUtils.escapeXml10(result); } if (escapeCsv) { result = StringEscapeUtils.escapeCsv(result); diff --git a/core/src/main/java/org/apache/struts2/components/Push.java b/core/src/main/java/org/apache/struts2/components/Push.java index f5f428ba2b..94494d366b 100644 --- a/core/src/main/java/org/apache/struts2/components/Push.java +++ b/core/src/main/java/org/apache/struts2/components/Push.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,7 +16,6 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; import java.io.Writer; @@ -26,7 +23,7 @@ import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; /** * @@ -148,5 +145,5 @@ public boolean end(Writer writer, String body) { public void setValue(String value) { this.value = value; } - + } diff --git a/core/src/main/java/org/apache/struts2/components/Radio.java b/core/src/main/java/org/apache/struts2/components/Radio.java index 00c6616196..d0d3eb1465 100644 --- a/core/src/main/java/org/apache/struts2/components/Radio.java +++ b/core/src/main/java/org/apache/struts2/components/Radio.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,15 +16,12 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.views.annotations.StrutsTag; -import org.apache.struts2.views.annotations.StrutsTagAttribute; - -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; /** * @@ -60,7 +55,7 @@ allowDynamicAttributes = true) public class Radio extends ListUIBean { final public static String TEMPLATE = "radiomap"; - + public Radio(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { super(stack, request, response); } @@ -68,8 +63,15 @@ public Radio(ValueStack stack, HttpServletRequest request, HttpServletResponse r protected String getDefaultTemplate() { return TEMPLATE; } - - public void evaluateExtraParams() { - super.evaluateExtraParams(); + + /** + * Radio tag requires lazy evaluation as list of tags is dynamically generated using + * + * @return boolean true by default + */ + @Override + protected boolean lazyEvaluation() { + return true; } -} \ No newline at end of file + +} diff --git a/core/src/main/java/org/apache/struts2/components/Reset.java b/core/src/main/java/org/apache/struts2/components/Reset.java index e489de2a3a..c1ec34ca2b 100644 --- a/core/src/main/java/org/apache/struts2/components/Reset.java +++ b/core/src/main/java/org/apache/struts2/components/Reset.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,15 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** * diff --git a/core/src/main/java/org/apache/struts2/components/Script.java b/core/src/main/java/org/apache/struts2/components/Script.java new file mode 100644 index 0000000000..6cb14bc95d --- /dev/null +++ b/core/src/main/java/org/apache/struts2/components/Script.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.struts2.components; + +import org.apache.struts2.util.ValueStack; +import org.apache.struts2.views.annotations.StrutsTag; +import org.apache.struts2.views.annotations.StrutsTagAttribute; + +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; + + +/** + *

      + * Add nonce propagation feature to implement CSP in script tags + *

      + * + *

      + * The script tag allows the user to execute JavaScript. It also allows external resources to execute + * scripts which can be malicious. The s:script tag includes a nonce attribute that is being randomly + * generated with each request and only allows scripts with the valid nonce value to be executed. + *

      + * + *

      Examples

      + * + *
      + *
      + * <s:script ... />
      + *
      + * 
      + * + */ +@StrutsTag(name="script", + tldTagClass="org.apache.struts2.views.jsp.ui.ScriptTag", + description="Script tag automatically adds nonces to script blocks - should be used in combination with Struts' CSP Interceptor.", + allowDynamicAttributes=true) +public class Script extends ClosingUIBean { + + protected String async; + protected String charset; + protected String defer; + protected String src; + protected String type; + protected String referrerpolicy; + protected String nomodule; + protected String integrity; + protected String crossorigin; + + private static final String TEMPLATE = "script-close"; + private static final String OPEN_TEMPLATE = "script"; + + public Script(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { + super(stack, request, response); + } + + @Override + public String getDefaultOpenTemplate() { + return OPEN_TEMPLATE; + } + + @Override + protected String getDefaultTemplate() { + return TEMPLATE; + } + + @StrutsTagAttribute(description="HTML script async attribute") + public void setAsync(String async) { + this.async = async; + } + + @StrutsTagAttribute(description="HTML script charset attribute") + public void setCharset(String charset) { + this.charset = charset; + } + + @StrutsTagAttribute(description="HTML script defer attribute") + public void setDefer(String defer) { + this.defer = defer; + } + + @StrutsTagAttribute(description="HTML script src attribute") + public void setSrc(String src) { + this.src = src; + } + + @StrutsTagAttribute(description="HTML script type attribute") + public void setType(String type) { + this.type = type; + } + + @StrutsTagAttribute(description="HTML script referrerpolicy attribute") + public void setReferrerpolicy(String referrerpolicy) { + this.referrerpolicy = referrerpolicy; + } + + @StrutsTagAttribute(description="HTML script nomodule attribute") + public void setNomodule(String nomodule) { + this.nomodule = nomodule; + } + + @StrutsTagAttribute(description="HTML script integrity attribute") + public void setIntegrity(String integrity) { + this.integrity = integrity; + } + + @StrutsTagAttribute(description="HTML script crossorigin attribute") + public void setCrossorigin(String crossorigin) { + this.crossorigin = crossorigin; + } + + @Override + public boolean usesBody() { + return true; + } + + @Override + protected void evaluateExtraParams() { + super.evaluateExtraParams(); + + if (async != null) { + addParameter("async", findString(async)); + } + + if (charset != null) { + addParameter("charset", findString(charset)); + } + + if (defer != null) { + addParameter("defer", findString(defer)); + } + + if (src != null) { + addParameter("src", findString(src)); + } + + if (type != null) { + addParameter("type", findString(type)); + } + + if (referrerpolicy != null) { + addParameter("referrerpolicy", findString(referrerpolicy)); + } + + if (nomodule != null) { + addParameter("nomodule", findString(nomodule)); + } + + if (integrity != null) { + addParameter("integrity", findString(integrity)); + } + + if (crossorigin != null) { + addParameter("crossorigin", findString(crossorigin)); + } + } + +} diff --git a/core/src/main/java/org/apache/struts2/components/Select.java b/core/src/main/java/org/apache/struts2/components/Select.java index a21aaa94b8..f1a8e5b6df 100644 --- a/core/src/main/java/org/apache/struts2/components/Select.java +++ b/core/src/main/java/org/apache/struts2/components/Select.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,15 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; /** * diff --git a/core/src/main/java/org/apache/struts2/components/ServletUrlRenderer.java b/core/src/main/java/org/apache/struts2/components/ServletUrlRenderer.java index 314f3dea54..c6bfec306b 100644 --- a/core/src/main/java/org/apache/struts2/components/ServletUrlRenderer.java +++ b/core/src/main/java/org/apache/struts2/components/ServletUrlRenderer.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,20 +16,21 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.config.entities.ActionConfig; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.ActionContext; +import org.apache.struts2.ActionInvocation; +import org.apache.struts2.config.entities.ActionConfig; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.RequestDispatcher; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.StrutsException; import org.apache.struts2.dispatcher.mapper.ActionMapper; import org.apache.struts2.dispatcher.mapper.ActionMapping; +import org.apache.struts2.url.QueryStringParser; import org.apache.struts2.views.util.UrlHelper; import java.io.IOException; @@ -51,7 +50,9 @@ public class ServletUrlRenderer implements UrlRenderer { private ActionMapper actionMapper; private UrlHelper urlHelper; + private QueryStringParser queryStringParser; + @Override @Inject public void setActionMapper(ActionMapper mapper) { this.actionMapper = mapper; @@ -62,9 +63,15 @@ public void setUrlHelper(UrlHelper urlHelper) { this.urlHelper = urlHelper; } + @Inject + public void setQueryStringParser(QueryStringParser queryStringParser) { + this.queryStringParser = queryStringParser; + } + /** * {@inheritDoc} */ + @Override public void renderUrl(Writer writer, UrlProvider urlComponent) { String scheme = urlComponent.getHttpServletRequest().getScheme(); @@ -77,7 +84,7 @@ public void renderUrl(Writer writer, UrlProvider urlComponent) { } String result; - ActionInvocation ai = (ActionInvocation) ActionContext.getContext().get(ActionContext.ACTION_INVOCATION); + ActionInvocation ai = ActionContext.getContext().getActionInvocation(); if (urlComponent.getValue() == null && urlComponent.getAction() != null) { result = urlComponent.determineActionURL(urlComponent.getAction(), urlComponent.getNamespace(), urlComponent.getMethod(), urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp()); } else if (urlComponent.getValue() == null && urlComponent.getAction() == null && ai != null) { @@ -92,14 +99,14 @@ public void renderUrl(Writer writer, UrlProvider urlComponent) { // We don't include the request parameters cause they would have been // prioritised before this [in start(Writer) method] - if (_value != null && _value.indexOf("?") > 0) { - _value = _value.substring(0, _value.indexOf("?")); + if (_value != null && _value.indexOf('?') > 0) { + _value = _value.substring(0, _value.indexOf('?')); } result = urlHelper.buildUrl(_value, urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp()); } - String anchor = urlComponent.getAnchor(); - if (StringUtils.isNotEmpty(anchor)) { - result += '#' + urlComponent.findString(anchor); + if (StringUtils.isNotEmpty(urlComponent.getAnchor())) { + String anchor = urlComponent.findString(urlComponent.getAnchor()); + result += '#' + anchor; } if (urlComponent.isPutInContext()) { @@ -107,7 +114,8 @@ public void renderUrl(Writer writer, UrlProvider urlComponent) { if (StringUtils.isNotEmpty(var)) { urlComponent.putInContext(result); - // add to the request and page scopes as well + // Note: Old comments stated that var was placed in the page scope, but interactive checks with EL on JSPs prove otherwise. + // Add the var attribute to the request scope as well. urlComponent.getHttpServletRequest().setAttribute(var, result); } else { try { @@ -128,6 +136,7 @@ public void renderUrl(Writer writer, UrlProvider urlComponent) { /** * {@inheritDoc} */ + @Override public void renderFormUrl(Form formComponent) { String namespace = formComponent.determineNamespace(formComponent.namespace, formComponent.getStack(), formComponent.request); String action; @@ -140,8 +149,7 @@ public void renderFormUrl(Form formComponent) { } else { // no action supplied? ok, then default to the current request // (action or general URL) - ActionInvocation ai = (ActionInvocation) formComponent.getStack().getContext().get( - ActionContext.ACTION_INVOCATION); + ActionInvocation ai = formComponent.getStack().getActionContext().getActionInvocation(); if (ai != null) { action = ai.getProxy().getActionName(); namespace = ai.getProxy().getNamespace(); @@ -152,11 +160,11 @@ public void renderFormUrl(Form formComponent) { } } - Map actionParams = null; - if (action != null && action.indexOf("?") > 0) { - String queryString = action.substring(action.indexOf("?") + 1); - actionParams = urlHelper.parseQueryString(queryString, false); - action = action.substring(0, action.indexOf("?")); + QueryStringParser.Result queryStringResult = queryStringParser.empty(); + if (action != null && action.indexOf('?') > 0) { + String queryString = action.substring(action.indexOf('?') + 1); + queryStringResult = queryStringParser.parse(queryString); + action = action.substring(0, action.indexOf('?')); } ActionMapping nameMapping = actionMapper.getMappingFromActionName(action); @@ -164,19 +172,19 @@ public void renderFormUrl(Form formComponent) { String actionMethod = nameMapping.getMethod(); final ActionConfig actionConfig = formComponent.configuration.getRuntimeConfiguration().getActionConfig( - namespace, actionName); + namespace, actionName); if (actionConfig != null) { - ActionMapping mapping = new ActionMapping(actionName, namespace, actionMethod, formComponent.parameters); + ActionMapping mapping = new ActionMapping(actionName, namespace, actionMethod, formComponent.attributes); String result = urlHelper.buildUrl(formComponent.actionMapper.getUriFromActionMapping(mapping), - formComponent.request, formComponent.response, actionParams, scheme, formComponent.includeContext, true, false, false); + formComponent.request, formComponent.response, queryStringResult.getQueryParams(), scheme, formComponent.includeContext, true, false, false); formComponent.addParameter("action", result); // let's try to get the actual action class and name // this can be used for getting the list of validators formComponent.addParameter("actionName", actionName); try { - Class clazz = formComponent.objectFactory.getClassInstance(actionConfig.getClassName()); + Class clazz = formComponent.objectFactory.getClassInstance(actionConfig.getClassName()); formComponent.addParameter("actionClass", clazz); } catch (ClassNotFoundException e) { // this is OK, we'll just move on @@ -191,7 +199,9 @@ public void renderFormUrl(Form formComponent) { // if the id isn't specified, use the action name if (formComponent.getId() == null && actionName != null) { - formComponent.addParameter("id", formComponent.escape(actionName)); + String escapedId = formComponent.escape(actionName); + formComponent.addParameter("id", escapedId); + formComponent.addParameter("escapedId", escapedId); } } else if (action != null) { // Since we can't find an action alias in the configuration, we just @@ -204,7 +214,7 @@ public void renderFormUrl(Form formComponent) { LOG.warn("No configuration found for the specified action: '{}' in namespace: '{}'. Form action defaulting to 'action' attribute's literal value.", actionName, namespace); } - String result = urlHelper.buildUrl(action, formComponent.request, formComponent.response, actionParams, scheme, formComponent.includeContext, true); + String result = urlHelper.buildUrl(action, formComponent.request, formComponent.response, queryStringResult.getQueryParams(), scheme, formComponent.includeContext, true); formComponent.addParameter("action", result); // namespace: cut out anything between the start and the last / @@ -226,7 +236,9 @@ public void renderFormUrl(Form formComponent) { } else { id = result.substring(slash + 1); } - formComponent.addParameter("id", formComponent.escape(id)); + String escapedId = formComponent.escape(id); + formComponent.addParameter("id", escapedId); + formComponent.addParameter("escapedId", escapedId); } } @@ -237,6 +249,7 @@ public void renderFormUrl(Form formComponent) { } + @Override public void beforeRenderUrl(UrlProvider urlComponent) { if (urlComponent.getValue() != null) { urlComponent.setValue(urlComponent.findString(urlComponent.getValue())); @@ -253,7 +266,7 @@ public void beforeRenderUrl(UrlProvider urlComponent) { } if (UrlProvider.NONE.equalsIgnoreCase(includeParams)) { - mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), Collections.emptyMap()); + mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), Collections.emptyMap()); } else if (UrlProvider.ALL.equalsIgnoreCase(includeParams)) { mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), urlComponent.getHttpServletRequest().getParameterMap()); @@ -279,14 +292,18 @@ private void includeExtraParameters(UrlProvider urlComponent) { private void includeGetParameters(UrlProvider urlComponent) { String query = extractQueryString(urlComponent); - mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), urlHelper.parseQueryString(query, false)); + QueryStringParser.Result result = queryStringParser.parse(query); + result = mergeRequestParameters(urlComponent.getValue(), urlComponent.getParameters(), result.getQueryParams()); + if (!result.getQueryFragment().isEmpty()) { + urlComponent.setAnchor(result.getQueryFragment()); + } } private String extractQueryString(UrlProvider urlComponent) { // Parse the query string to make sure that the parameters come from the query, and not some posted data String query = urlComponent.getHttpServletRequest().getQueryString(); if (query == null) { - query = (String) urlComponent.getHttpServletRequest().getAttribute("javax.servlet.forward.query_string"); + query = (String) urlComponent.getHttpServletRequest().getAttribute(RequestDispatcher.FORWARD_QUERY_STRING); } if (query != null) { @@ -302,9 +319,9 @@ private String extractQueryString(UrlProvider urlComponent) { /** * Merge request parameters into current parameters. If a parameter is - * already present, than the request parameter in the current request and value atrribute + * already present, than the request parameter in the current request and value attribute * will not override its value. - * + *

      * The priority is as follows:- *

        *
      • parameter from the current request (least priority)
      • @@ -312,23 +329,25 @@ private String extractQueryString(UrlProvider urlComponent) { *
      • parameter from the param tag (most priority)
      • *
      * - * @param value the value attribute (url to be generated by this component) - * @param parameters component parameters + * @param value the value attribute (URL to be generated by this component) + * @param parameters component parameters * @param contextParameters request parameters + * @return {@link QueryStringParser.Result} of value's ?query-string or empty() */ - protected void mergeRequestParameters(String value, Map parameters, Map contextParameters) { - + protected QueryStringParser.Result mergeRequestParameters(String value, Map parameters, Map contextParameters) { Map mergedParams = new LinkedHashMap<>(contextParameters); + QueryStringParser.Result result = queryStringParser.empty(); // Merge contextParameters (from current request) with parameters specified in value attribute // eg. value="someAction.action?id=someId&venue=someVenue" // where the parameters specified in value attribute takes priority. if (StringUtils.contains(value, "?")) { - String queryString = value.substring(value.indexOf("?") + 1); + String queryString = value.substring(value.indexOf('?') + 1); - mergedParams = urlHelper.parseQueryString(queryString, false); - for (Map.Entry entry : contextParameters.entrySet()) { + result = queryStringParser.parse(queryString); + mergedParams = new LinkedHashMap<>(result.getQueryParams()); + for (Map.Entry entry : contextParameters.entrySet()) { if (!mergedParams.containsKey(entry.getKey())) { mergedParams.put(entry.getKey(), entry.getValue()); } @@ -346,6 +365,8 @@ protected void mergeRequestParameters(String value, Map paramete parameters.put(entry.getKey(), entry.getValue()); } } + + return result; } } diff --git a/core/src/main/java/org/apache/struts2/components/Set.java b/core/src/main/java/org/apache/struts2/components/Set.java index 7e1ca021d4..19198e4e57 100644 --- a/core/src/main/java/org/apache/struts2/components/Set.java +++ b/core/src/main/java/org/apache/struts2/components/Set.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,15 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import java.io.Writer; - +import org.apache.struts2.util.ValueStack; +import org.apache.struts2.dispatcher.DispatcherConstants; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import com.opensymphony.xwork2.util.ValueStack; +import java.io.Writer; /** * @@ -34,8 +31,7 @@ * complex expression and then simply reference that variable each time rather than the complex expression. This is * useful in both cases: when the complex expression takes time (performance improvement) or is hard to read (code * readability improvement).

      - *

      If the tag is used with body content, the evaluation of the value parameter is omitted. Instead, the String to - * which the body evaluates is set as value for the scoped variable.

      + *

      If the value parameter is omitted, the String to which the body evaluates is set as value for the scoped variable.

      * *

      The scopes available are as follows:

      *
        @@ -57,14 +53,11 @@ * * *
          - * *
        • var* (String): The name of the new variable that is assigned the value of value
        • - * *
        • value (Object): The value that is assigned to the variable named name
        • - * *
        • scope (String): The scope in which to assign the variable. Can be application, session, * request, page, or action. By default it is action.
        • - * + *
        • Note: With the action scope, the variable is also assigned to the page scope. *
        * * @@ -82,24 +75,26 @@ * * */ -@StrutsTag(name="set", tldBodyContent="JSP", tldTagClass="org.apache.struts2.views.jsp.SetTag", description="Assigns a value to a variable in a specified scope") +@StrutsTag(name="set", tldTagClass="org.apache.struts2.views.jsp.SetTag", description="Assigns a value to a variable in a specified scope") public class Set extends ContextBean { protected String scope; protected String value; + protected boolean trimBody = true; public Set(ValueStack stack) { super(stack); } + @Override public boolean end(Writer writer, String body) { ValueStack stack = getStack(); Object o; if (value == null) { - if (body != null && !body.equals("")) { - o = body; - } else { + if (body == null) { o = findValue("top"); + } else { + o = body; } } else { o = findValue(value); @@ -107,29 +102,32 @@ public boolean end(Writer writer, String body) { body=""; - if ("application".equalsIgnoreCase(scope)) { - stack.setValue("#application['" + getVar() + "']", o); - } else if ("session".equalsIgnoreCase(scope)) { - stack.setValue("#session['" + getVar() + "']", o); - } else if ("request".equalsIgnoreCase(scope)) { - stack.setValue("#request['" + getVar() + "']", o); - } else if ("page".equalsIgnoreCase(scope)) { - stack.setValue("#attr['" + getVar() + "']", o, false); + if (DispatcherConstants.APPLICATION.equalsIgnoreCase(scope)) { + stack.setValue(String.format("#application[\"%s\"]", getVar()), o); + } else if (DispatcherConstants.SESSION.equalsIgnoreCase(scope)) { + stack.setValue(String.format("#session[\"%s\"]", getVar()), o); + } else if (DispatcherConstants.REQUEST.equalsIgnoreCase(scope)) { + stack.setValue(String.format("#request[\"%s\"]", getVar()), o); + } else if (DispatcherConstants.PAGE.equalsIgnoreCase(scope)) { + stack.setValue(String.format("#attr[\"%s\"]", getVar()), o, false); } else { - stack.getContext().put(getVar(), o); - stack.setValue("#attr['" + getVar() + "']", o, false); + // Default scope is action. Note: The action scope handling also adds the var to the page scope. + putInContext(o); + stack.setValue(String.format("#attr[\"%s\"]", getVar()), o, false); } return super.end(writer, body); } - @StrutsTagAttribute(required=true, description="Name used to reference the value pushed into the Value Stack") + @StrutsTagAttribute(required=true, description="Name used to reference the value pushed into the Value Stack (default scope: action," + + "override with the scope attribute).") + @Override public void setVar(String var) { super.setVar(var); } @StrutsTagAttribute(description="The scope in which to assign the variable. Can be application" + - ", session, request, page, or action.", defaultValue="action") + ", session, request, page, or action (action scope also adds it to the page scope).", defaultValue="action") public void setScope(String scope) { this.scope = scope; } @@ -139,6 +137,11 @@ public void setValue(String value) { this.value = value; } + @StrutsTagAttribute(description="Set to false to prevent the default whitespace-trim of this tag's body content", type="Boolean", defaultValue="true") + public void setTrimBody(boolean trimBody) { + this.trimBody = trimBody; + } + @Override public boolean usesBody() { return true; diff --git a/core/src/main/java/org/apache/struts2/components/Submit.java b/core/src/main/java/org/apache/struts2/components/Submit.java index 85fb0d2e6c..47024e99c9 100644 --- a/core/src/main/java/org/apache/struts2/components/Submit.java +++ b/core/src/main/java/org/apache/struts2/components/Submit.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,18 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; import java.io.Writer; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; @@ -75,7 +72,7 @@ public void evaluateParams() { value = "Submit"; } - if (((key != null)) && (value == null)) { + if ((key != null) && (value == null)) { this.value = "%{getText('"+key +"')}"; } @@ -85,8 +82,11 @@ public void evaluateParams() { public void evaluateExtraParams() { super.evaluateExtraParams(); - if (src != null) + if (src != null) { addParameter("src", findString(src)); + } + + addParameter("escapeHtmlBody", escapeHtmlBody); } /** @@ -103,6 +103,10 @@ public void setSrc(String src) { this.src = src; } + @StrutsTagAttribute(description = "Specifies whether to HTML-escape the tag body or not", type = "Boolean", defaultValue = "false") + public void setEscapeHtmlBody(boolean escapeHtmlBody) { + this.escapeHtmlBody = escapeHtmlBody; + } @Override public boolean usesBody() { diff --git a/core/src/main/java/org/apache/struts2/components/Text.java b/core/src/main/java/org/apache/struts2/components/Text.java index 3f7c15e9e2..4f9ea316d6 100644 --- a/core/src/main/java/org/apache/struts2/components/Text.java +++ b/core/src/main/java/org/apache/struts2/components/Text.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,10 +16,10 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; +import org.apache.commons.text.StringEscapeUtils; import org.apache.commons.lang3.StringUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; @@ -51,9 +49,14 @@ * *

        * If the named message is not found in a property file, then the body of the - * tag will be used as default message. If no body is used, then the stack can - * be searched, and if a value is returned, it will written to the output. - * If no value is found on the stack, the key of the message will be written out. + * tag will be used as default message. If no value is found, the key of the + * message will not be written out. + *

        + * + *

        + * Note: If the var attribute is used with this tag, the tag's value will + * not be written out. Instead the result will be saved into the + * action context (action scope). *

        * * @@ -61,6 +64,10 @@ * *
          *
        • name* (String) - the i18n message key
        • + *
        • escapeHtml (Boolean) - Escape HTML. Defaults to false
        • + *
        • escapeJavaScript (Boolean) - Escape JavaScript. Defaults to false
        • + *
        • escapeXml (Boolean) - Escape XML. Defaults to false
        • + *
        • escapeCsv (Boolean) - Escape CSV. Defaults to false
        • *
        * * @@ -121,7 +128,10 @@ public class Text extends ContextBean implements Param.UnnamedParametric { protected List values = Collections.emptyList(); protected String actualName; protected String name; - protected String searchStack; + private boolean escapeHtml = false; + private boolean escapeJavaScript = false; + private boolean escapeXml = false; + private boolean escapeCsv = false; public Text(ValueStack stack) { super(stack); @@ -132,11 +142,27 @@ public void setName(String name) { this.name = name; } - @StrutsTagAttribute(description="Search the stack if property is not found on resources", type = "Boolean", defaultValue = "false") - public void setSearchValueStack(String searchStack) { - this.searchStack = searchStack; + @StrutsTagAttribute(description="Whether to escape HTML", type="Boolean", defaultValue="false") + public void setEscapeHtml(boolean escape) { + this.escapeHtml = escape; + } + + @StrutsTagAttribute(description="Whether to escape Javascript", type="Boolean", defaultValue="false") + public void setEscapeJavaScript(boolean escapeJavaScript) { + this.escapeJavaScript = escapeJavaScript; + } + + @StrutsTagAttribute(description="Whether to escape XML", type="Boolean", defaultValue="false") + public void setEscapeXml(boolean escapeXml) { + this.escapeXml = escapeXml; + } + + @StrutsTagAttribute(description="Whether to escape CSV (useful to escape a value for a column)", type="Boolean", defaultValue="false") + public void setEscapeCsv(boolean escapeCsv) { + this.escapeCsv = escapeCsv; } + @Override public boolean usesBody() { // overriding this to true such that EVAL_BODY_BUFFERED is return and // bodyContent will be valid hence, text between start & end tag will @@ -144,6 +170,7 @@ public boolean usesBody() { return true; } + @Override public boolean end(Writer writer, String body) { actualName = findString(name, "name", "You must specify the i18n key. Example: welcome.header"); String defaultMessage; @@ -153,18 +180,12 @@ public boolean end(Writer writer, String body) { defaultMessage = actualName; } - Boolean doSearchStack = false; - if (searchStack != null) { - Object value = findValue(searchStack, Boolean.class); - doSearchStack = value != null ? (Boolean) value : false; - } - - String msg = TextProviderHelper.getText(actualName, defaultMessage, values, getStack(), doSearchStack); + String msg = TextProviderHelper.getText(actualName, defaultMessage, values, getStack()); if (msg != null) { try { if (getVar() == null) { - writer.write(msg); + writer.write(prepare(msg)); } else { putInContext(msg); } @@ -176,10 +197,12 @@ public boolean end(Writer writer, String body) { return super.end(writer, ""); } + @Override public void addParameter(String key, Object value) { addParameter(value); } + @Override public void addParameter(Object value) { if (values.isEmpty()) { values = new ArrayList<>(4); @@ -187,4 +210,22 @@ public void addParameter(Object value) { values.add(value); } + + private String prepare(String value) { + String result = value; + if (escapeHtml) { + result = StringEscapeUtils.escapeHtml4(result); + } + if (escapeJavaScript) { + result = StringEscapeUtils.escapeEcmaScript(result); + } + if (escapeXml) { + result = StringEscapeUtils.escapeXml10(result); + } + if (escapeCsv) { + result = StringEscapeUtils.escapeCsv(result); + } + + return result; + } } diff --git a/core/src/main/java/org/apache/struts2/components/TextArea.java b/core/src/main/java/org/apache/struts2/components/TextArea.java index 234810df46..7f3babf561 100644 --- a/core/src/main/java/org/apache/struts2/components/TextArea.java +++ b/core/src/main/java/org/apache/struts2/components/TextArea.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,15 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; /** * @@ -54,6 +51,8 @@ public class TextArea extends UIBean { protected String readonly; protected String rows; protected String wrap; + protected String maxlength; + protected String minlength; public TextArea(ValueStack stack, HttpServletRequest request, HttpServletResponse response) { super(stack, request, response); @@ -81,6 +80,13 @@ public void evaluateExtraParams() { if (wrap != null) { addParameter("wrap", findString(wrap)); } + + if (maxlength != null) { + addParameter("maxlength", findString(maxlength)); + } + if (minlength != null) { + addParameter("minlength", findString(minlength)); + } } @StrutsTagAttribute(description="HTML cols attribute", type="Integer") @@ -102,4 +108,14 @@ public void setRows(String rows) { public void setWrap(String wrap) { this.wrap = wrap; } + + @StrutsTagAttribute(description="HTML maxlength attribute", type="Integer") + public void setMaxlength(String maxlength) { + this.maxlength = maxlength; + } + + @StrutsTagAttribute(description="HTML minlength attribute", type="Integer") + public void setMinlength(String minlength) { + this.minlength = minlength; + } } diff --git a/core/src/main/java/org/apache/struts2/components/TextField.java b/core/src/main/java/org/apache/struts2/components/TextField.java index a5b73651b7..726c4fc5b3 100644 --- a/core/src/main/java/org/apache/struts2/components/TextField.java +++ b/core/src/main/java/org/apache/struts2/components/TextField.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,16 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import org.apache.struts2.util.ValueStack; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.views.annotations.StrutsTagAttribute; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; - /** * *

        Render an HTML input field of type text

        @@ -53,17 +49,16 @@ * */ @StrutsTag( - name="textfield", - tldTagClass="org.apache.struts2.views.jsp.ui.TextFieldTag", - description="Render an HTML input field of type text", - allowDynamicAttributes=true) + name = "textfield", + tldTagClass = "org.apache.struts2.views.jsp.ui.TextFieldTag", + description = "Render an HTML input field of type text", + allowDynamicAttributes = true) public class TextField extends UIBean { /** * The name of the default template for the TextFieldTag */ final public static String TEMPLATE = "text"; - protected String maxlength; protected String readonly; protected String size; @@ -98,27 +93,22 @@ protected void evaluateExtraParams() { } - @StrutsTagAttribute(description="HTML maxlength attribute", type="Integer") + @StrutsTagAttribute(description = "HTML maxlength attribute", type = "Integer") public void setMaxlength(String maxlength) { this.maxlength = maxlength; } - @StrutsTagAttribute(description="Deprecated. Use maxlength instead.", type="Integer") - public void setMaxLength(String maxlength) { - this.maxlength = maxlength; - } - - @StrutsTagAttribute(description="Whether the input is readonly", type="Boolean", defaultValue="false") + @StrutsTagAttribute(description = "Whether the input is readonly", type = "Boolean", defaultValue = "false") public void setReadonly(String readonly) { this.readonly = readonly; } - @StrutsTagAttribute(description="HTML size attribute", type="Integer") + @StrutsTagAttribute(description = "HTML size attribute", type = "Integer") public void setSize(String size) { this.size = size; } - @StrutsTagAttribute(description="Specifies the html5 type element to display. e.g. text, email, url", defaultValue="text") + @StrutsTagAttribute(description = "Specifies the html5 type element to display. e.g. text, email, url", defaultValue = "text") public void setType(String type) { this.type = type; } diff --git a/core/src/main/java/org/apache/struts2/components/Token.java b/core/src/main/java/org/apache/struts2/components/Token.java index cac7679453..e5bc6a2baa 100644 --- a/core/src/main/java/org/apache/struts2/components/Token.java +++ b/core/src/main/java/org/apache/struts2/components/Token.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,18 +16,17 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; import java.util.Map; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.struts2.views.annotations.StrutsTag; import org.apache.struts2.util.TokenHelper; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.util.ValueStack; /** * @@ -76,7 +73,7 @@ protected void evaluateExtraParams() { super.evaluateExtraParams(); String tokenName; - Map parameters = getParameters(); + Map parameters = getAttributes(); if (parameters.containsKey("name")) { tokenName = (String) parameters.get("name"); diff --git a/core/src/main/java/org/apache/struts2/components/UIBean.java b/core/src/main/java/org/apache/struts2/components/UIBean.java index 38673c9a16..0d54290991 100644 --- a/core/src/main/java/org/apache/struts2/components/UIBean.java +++ b/core/src/main/java/org/apache/struts2/components/UIBean.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,13 +16,16 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components; -import com.opensymphony.xwork2.config.ConfigurationException; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; -import org.apache.commons.lang3.StringUtils; +import org.apache.struts2.config.ConfigurationException; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.TextParseUtil; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.http.HttpSession; +import org.apache.commons.lang3.ObjectUtils; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.StrutsConstants; @@ -33,17 +34,23 @@ import org.apache.struts2.components.template.TemplateEngine; import org.apache.struts2.components.template.TemplateEngineManager; import org.apache.struts2.components.template.TemplateRenderingContext; +import org.apache.struts2.dispatcher.AttributeMap; +import org.apache.struts2.dispatcher.StaticContentLoader; +import org.apache.struts2.util.ComponentUtils; import org.apache.struts2.util.TextProviderHelper; import org.apache.struts2.views.annotations.StrutsTagAttribute; import org.apache.struts2.views.util.ContextUtil; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.Writer; import java.util.HashMap; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; + +import static java.util.Collections.emptyMap; +import static org.apache.commons.lang3.StringUtils.isBlank; +import static org.apache.struts2.dispatcher.DispatcherConstants.ATTRIBUTES; /** *

        @@ -297,7 +304,7 @@ * * * - * + * Deprecated since 7.0.1 * * Attribute @@ -320,7 +327,7 @@ * * tooltipIcon * String - * /struts/static/tooltip/tooltip.gif + * /static/tooltip/tooltip.gif * The url to the tooltip icon * * tooltipDelay @@ -341,7 +348,7 @@ * * *

        - * tooltipConfig is deprecated, use individual tooltip configuration attributes instead + * tooltipConfig is deprecated, use individual tooltip configuration attributes instead *

        * *

        @@ -377,7 +384,7 @@ * *

          * 
        - *
        + * Deprecated since 7.0.1
          * <!-- Example 1: -->
          * <s:form
          *          tooltipDelay="500"
        @@ -434,8 +441,16 @@
          *
          */
         public abstract class UIBean extends Component {
        +
             private static final Logger LOG = LogManager.getLogger(UIBean.class);
         
        +    static final String TEMPLATE_DIR = "templateDir";
        +    static final String THEME = "theme";
        +
        +    protected static final String ATTR_FIELD_VALUE = "fieldValue";
        +    protected static final String ATTR_NAME_VALUE = "nameValue";
        +    protected static final String ATTR_VALUE = "value";
        +
             protected HttpServletRequest request;
             protected HttpServletResponse response;
         
        @@ -509,6 +524,8 @@ public UIBean(ValueStack stack, HttpServletRequest request, HttpServletResponse
             protected String defaultTemplateDir;
             protected String defaultUITheme;
             protected String uiThemeExpansionToken;
        +    protected String uiStaticContentPath;
        +
             protected TemplateEngineManager templateEngineManager;
         
             @Inject(StrutsConstants.STRUTS_UI_TEMPLATEDIR)
        @@ -526,11 +543,17 @@ public void setUIThemeExpansionToken(String uiThemeExpansionToken) {
                 this.uiThemeExpansionToken = uiThemeExpansionToken;
             }
         
        +    @Inject(StrutsConstants.STRUTS_UI_STATIC_CONTENT_PATH)
        +    public void setStaticContentPath(String uiStaticContentPath) {
        +        this.uiStaticContentPath = StaticContentLoader.Validator.validateStaticContentPath(uiStaticContentPath);
        +    }
        +
             @Inject
             public void setTemplateEngineManager(TemplateEngineManager mgr) {
                 this.templateEngineManager = mgr;
             }
         
        +    @Override
             public boolean end(Writer writer, String body) {
                 evaluateParams();
                 try {
        @@ -557,16 +580,13 @@ public boolean end(Writer writer, String body) {
             protected abstract String getDefaultTemplate();
         
             protected Template buildTemplateName(String myTemplate, String myDefaultTemplate) {
        -        String template = myDefaultTemplate;
        +        String templateName = myDefaultTemplate;
         
                 if (myTemplate != null) {
        -            template = findString(myTemplate);
        +            templateName = findString(myTemplate);
                 }
         
        -        String templateDir = getTemplateDir();
        -        String theme = getTheme();
        -
        -        return new Template(templateDir, theme, template);
        +        return new Template(getTemplateDir(), getTheme(), templateName);
         
             }
         
        @@ -578,82 +598,86 @@ protected void mergeTemplate(Writer writer, Template template) throws Exception
         
                 LOG.debug("Rendering template {}", template);
         
        -        final TemplateRenderingContext context = new TemplateRenderingContext(template, writer, getStack(), getParameters(), this);
        +        final TemplateRenderingContext context = new TemplateRenderingContext(template, writer, getStack(), getAttributes(), this);
                 engine.renderTemplate(context);
             }
         
             public String getTemplateDir() {
        -        String templateDir = null;
        +        String result = null;
         
                 if (this.templateDir != null) {
        -            templateDir = findString(this.templateDir);
        +            result = findString(this.templateDir);
                 }
         
        -        // If templateDir is not explicitly given,
        -        // try to find attribute which states the dir set to use
        -        if (StringUtils.isBlank(templateDir)) {
        -            templateDir = stack.findString("#attr.templateDir");
        +        // Check Request, Session, Application scopes
        +        if (isBlank(result)) {
        +            result = (String) getAttrMap().get(TEMPLATE_DIR);
                 }
         
                 // Default template set
        -        if (StringUtils.isBlank(templateDir)) {
        -            templateDir = defaultTemplateDir;
        +        if (isBlank(result)) {
        +            result = defaultTemplateDir;
                 }
         
                 // Defaults to 'template'
        -        if (StringUtils.isBlank(templateDir)) {
        -            templateDir = "template";
        +        if (isBlank(result)) {
        +            result = "template";
                 }
         
        -        return templateDir;
        +        return result;
             }
         
             public String getTheme() {
        -        String theme = null;
        +        String result = null;
         
                 if (this.theme != null) {
        -            theme = findString(this.theme);
        +            result = findString(this.theme);
                 }
         
        -        if (StringUtils.isBlank(theme)) {
        +        if (isBlank(result)) {
                     Form form = (Form) findAncestor(Form.class);
                     if (form != null) {
        -                theme = form.getTheme();
        +                result = form.getTheme();
                     }
                 }
         
        -        // If theme set is not explicitly given,
        -        // try to find attribute which states the theme set to use
        -        if (StringUtils.isBlank(theme)) {
        -            theme = stack.findString("#attr.theme");
        +        // Check Request, Session, Application scopes
        +        if (isBlank(result)) {
        +            result = (String) getAttrMap().get(THEME);
                 }
         
                 // Default theme set
        -        if (StringUtils.isBlank(theme)) {
        -            theme = defaultUITheme;
        +        if (isBlank(result)) {
        +            result = defaultUITheme;
                 }
         
        -        return theme;
        +        return result;
        +    }
        +
        +    private Map getAttrMap() {
        +        AttributeMap attrMap = (AttributeMap) getStack().getContext().get(ATTRIBUTES);
        +        return attrMap != null ? attrMap : emptyMap();
             }
         
             public void evaluateParams() {
        -        String templateDir = getTemplateDir();
        -        String theme = getTheme();
        -        
        -        addParameter("templateDir", templateDir);
        -        addParameter("theme", theme);
        +        String gotTheme = getTheme();
        +
        +        addParameter(TEMPLATE_DIR, getTemplateDir());
        +        addParameter(THEME, gotTheme);
                 addParameter("template", template != null ? findString(template) : getDefaultTemplate());
                 addParameter("dynamicAttributes", dynamicAttributes);
                 addParameter("themeExpansionToken", uiThemeExpansionToken);
        -        addParameter("expandTheme", uiThemeExpansionToken + theme);
        +        addParameter("expandTheme", uiThemeExpansionToken + gotTheme);
         
        -        String name = null;
        +        addParameter("staticContentPath", findString(uiStaticContentPath));
        +
        +        String translatedName = null;
                 String providedLabel = null;
         
                 if (this.key != null) {
         
                     if(this.name == null) {
        -                this.name = key;
        +                setName(key);
                     }
         
                     if(this.label == null) {
        @@ -663,8 +687,8 @@ public void evaluateParams() {
                 }
         
                 if (this.name != null) {
        -            name = findString(this.name);
        -            addParameter("name", name);
        +            translatedName = findString(this.name);
        +            addParameter("name", translatedName);
                 }
         
                 if (label != null) {
        @@ -681,7 +705,8 @@ public void evaluateParams() {
                 }
         
                 if (labelPosition != null) {
        -            addParameter("labelposition", findString(labelPosition));
        +            String labelPosition = findString(this.labelPosition);
        +            addParameter("labelPosition", labelPosition);
                 }
         
                 if (requiredPosition != null) {
        @@ -691,13 +716,15 @@ public void evaluateParams() {
                 if (errorPosition != null) {
                     addParameter("errorposition", findString(errorPosition));
                 }
        -        
        +
                 if (requiredLabel != null) {
        -            addParameter("required", findValue(requiredLabel, Boolean.class));
        +            Object parsedValue = findValue(requiredLabel, Boolean.class);
        +            addParameter("required", parsedValue == null ? Boolean.valueOf(requiredLabel) : parsedValue);
                 }
         
                 if (disabled != null) {
        -            addParameter("disabled", findValue(disabled, Boolean.class));
        +            Object parsedValue = findValue(disabled, Boolean.class);
        +            addParameter("disabled", parsedValue == null ? Boolean.valueOf(disabled) : parsedValue);
                 }
         
                 if (tabindex != null) {
        @@ -784,31 +811,7 @@ public void evaluateParams() {
                     addParameter("title", findString(title));
                 }
         
        -
        -        // see if the value was specified as a parameter already
        -        if (parameters.containsKey("value")) {
        -            parameters.put("nameValue", parameters.get("value"));
        -        } else {
        -            if (evaluateNameValue()) {
        -                final Class valueClazz = getValueClassType();
        -
        -                if (valueClazz != null) {
        -                    if (value != null) {
        -                        addParameter("nameValue", findValue(value, valueClazz));
        -                    } else if (name != null) {
        -                        String expr = completeExpressionIfAltSyntax(name);
        -
        -                        addParameter("nameValue", findValue(expr, valueClazz));
        -                    }
        -                } else {
        -                    if (value != null) {
        -                        addParameter("nameValue", findValue(value));
        -                    } else if (name != null) {
        -                        addParameter("nameValue", findValue(name));
        -                    }
        -                }
        -            }
        -        }
        +        applyValueParameter(translatedName);
         
                 final Form form = (Form) findAncestor(Form.class);
         
        @@ -816,12 +819,12 @@ public void evaluateParams() {
                 populateComponentHtmlId(form);
         
                 if (form != null ) {
        -            addParameter("form", form.getParameters());
        +            addParameter("form", form.getAttributes());
         
        -            if ( name != null ) {
        +            if ( translatedName != null ) {
                         // list should have been created by the form component
        -                List tags = (List) form.getParameters().get("tagNames");
        -                tags.add(name);
        +                List tags = (List) form.getAttributes().get("tagNames");
        +                tags.add(translatedName);
                     }
                 }
         
        @@ -833,19 +836,18 @@ public void evaluateParams() {
                 if (tooltip != null) {
                     addParameter("tooltip", findString(tooltip));
         
        -            Map tooltipConfigMap = getTooltipConfig(this);
        +            Map tooltipConfigMap = getTooltipConfig(this);
         
                     if (form != null) { // inform the containing form that we need tooltip javascript included
                         form.addParameter("hasTooltip", Boolean.TRUE);
         
                         // tooltipConfig defined in component itself will take precedence
                         // over those defined in the containing form
        -                Map overallTooltipConfigMap = getTooltipConfig(form);
        +                Map overallTooltipConfigMap = getTooltipConfig(form);
                         overallTooltipConfigMap.putAll(tooltipConfigMap); // override parent form's tooltip config
         
        -                for (Object o : overallTooltipConfigMap.entrySet()) {
        -                    Map.Entry entry = (Map.Entry) o;
        -                    addParameter((String) entry.getKey(), entry.getValue());
        +                for (Map.Entry entry : overallTooltipConfigMap.entrySet()) {
        +                    addParameter(entry.getKey(), entry.getValue());
                         }
                     }
                     else {
        @@ -853,28 +855,28 @@ public void evaluateParams() {
                     }
         
                     //TODO: this is to keep backward compatibility, remove once when tooltipConfig is dropped
        -            String  jsTooltipEnabled = (String) getParameters().get("jsTooltipEnabled");
        +            String  jsTooltipEnabled = (String) getAttributes().get("jsTooltipEnabled");
                     if (jsTooltipEnabled != null)
                         this.javascriptTooltip = jsTooltipEnabled;
         
                     //TODO: this is to keep backward compatibility, remove once when tooltipConfig is dropped
        -            String tooltipIcon = (String) getParameters().get("tooltipIcon");
        +            String tooltipIcon = (String) getAttributes().get("tooltipIcon");
                     if (tooltipIcon != null)
                         this.addParameter("tooltipIconPath", tooltipIcon);
                     if (this.tooltipIconPath != null)
                         this.addParameter("tooltipIconPath", findString(this.tooltipIconPath));
         
                     //TODO: this is to keep backward compatibility, remove once when tooltipConfig is dropped
        -            String tooltipDelayParam = (String) getParameters().get("tooltipDelay");
        +            String tooltipDelayParam = (String) getAttributes().get("tooltipDelay");
                     if (tooltipDelayParam != null)
                         this.addParameter("tooltipDelay", tooltipDelayParam);
                     if (this.tooltipDelay != null)
                         this.addParameter("tooltipDelay", findString(this.tooltipDelay));
         
                     if (this.javascriptTooltip != null) {
        -                Boolean jsTooltips = (Boolean) findValue(this.javascriptTooltip, Boolean.class);
        +                Object jsTooltips = findValue(this.javascriptTooltip, Boolean.class);
                         //TODO use a Boolean model when tooltipConfig is dropped
        -                this.addParameter("jsTooltipEnabled", jsTooltips.toString());
        +                this.addParameter("jsTooltipEnabled", jsTooltips == null ? this.javascriptTooltip : jsTooltips.toString());
         
                         if (form != null)
                             form.addParameter("hasTooltip", jsTooltips);
        @@ -883,13 +885,63 @@ public void evaluateParams() {
                     }
                 }
         
        +        // to be used with the CSP interceptor - adds the nonce value as a parameter to be accessed from ftl files
        +        HttpSession session = stack.getActionContext().getServletRequest().getSession(false);
        +        Object nonceValue = session != null ? session.getAttribute("nonce") : null;
        +
        +        if (nonceValue != null) {
        +            addParameter("nonce", nonceValue.toString());
        +        } else {
        +            LOG.debug("Session is not active, cannot obtain nonce value");
        +        }
        +
                 evaluateExtraParams();
             }
         
        -	protected String escape(String name) {
        +    /**
        +     * Tries to calculate the "value" parameter based either on the provided {@link #value} or {@link #name}
        +     * @param translatedName the already evaluated {@link #name}
        +     */
        +    protected void applyValueParameter(String translatedName) {
        +        // see if the value has been specified as a parameter already
        +        if (attributes.containsKey(ATTR_VALUE)) {
        +            attributes.put(ATTR_NAME_VALUE, attributes.get(ATTR_VALUE));
        +        } else {
        +            if (evaluateNameValue()) {
        +                final Class valueClazz = getValueClassType();
        +
        +                if (valueClazz != null) {
        +                    if (value != null) {
        +                        addParameter(ATTR_NAME_VALUE, findValue(value, valueClazz));
        +                    } else if (translatedName != null) {
        +                        processTranslatedName(translatedName, (expr) -> findValue(expr, valueClazz));
        +                    }
        +                } else {
        +                    if (value != null) {
        +                        addParameter(ATTR_NAME_VALUE, findValue(value));
        +                    } else if (translatedName != null) {
        +                        processTranslatedName(translatedName, this::findValue);
        +                    }
        +                }
        +            }
        +        }
        +    }
        +
        +    private void processTranslatedName(String translatedName, Function evaluator) {
        +        boolean evaluated = !translatedName.equals(this.name);
        +        boolean reevaluate = !evaluated || isAcceptableExpression(translatedName);
        +        if (!reevaluate) {
        +            addParameter(ATTR_NAME_VALUE, translatedName);
        +        } else {
        +            String expr = completeExpression(translatedName);
        +            addParameter(ATTR_NAME_VALUE, evaluator.apply(expr));
        +        }
        +    }
        +
        +    protected String escape(String name) {
                 // escape any possible values that can make the ID painful to work with in JavaScript
                 if (name != null) {
        -            return name.replaceAll("[\\/\\.\\[\\]]", "_");
        +            return name.replaceAll("[^a-zA-Z0-9_]", "_");
                 } else {
                     return null;
                 }
        @@ -916,7 +968,7 @@ protected boolean evaluateNameValue() {
                 return true;
             }
         
        -    protected Class getValueClassType() {
        +    protected Class getValueClassType() {
                 return String.class;
             }
         
        @@ -933,47 +985,47 @@ protected void enableAncestorFormCustomOnsubmit() {
                     form.addParameter("customOnsubmitEnabled", Boolean.TRUE);
                 } else {
                     if (LOG.isWarnEnabled()) {
        -        	LOG.warn("Cannot find an Ancestor form, custom onsubmit is NOT enabled");
        +                LOG.warn("Cannot find an Ancestor form, custom onsubmit is NOT enabled");
                     }
                 }
             }
         
        -    protected Map getTooltipConfig(UIBean component) {
        -        Object tooltipConfigObj = component.getParameters().get("tooltipConfig");
        -        Map tooltipConfig = new LinkedHashMap<>();
        +    @Deprecated(since = "7.0.1", forRemoval = true)
        +    protected Map getTooltipConfig(UIBean component) {
        +        Object tooltipConfigObj = component.getAttributes().get("tooltipConfig");
        +        Map result = new LinkedHashMap<>();
         
                 if (tooltipConfigObj instanceof Map) {
                     // we get this if its configured using
                     // 1] UI component's tooltipConfig attribute  OR
                     // 2]  param tag value attribute
         
        -            tooltipConfig = new LinkedHashMap<>((Map) tooltipConfigObj);
        -        } else if (tooltipConfigObj instanceof String) {
        +            result = new LinkedHashMap((Map) tooltipConfigObj);
        +        } else if (tooltipConfigObj instanceof String tooltipConfigStr) {
         
                     // we get this if its configured using
                     //  ...  tag's body
        -            String tooltipConfigStr = (String) tooltipConfigObj;
                     String[] tooltipConfigArray = tooltipConfigStr.split("\\|");
         
                     for (String aTooltipConfigArray : tooltipConfigArray) {
                         String[] configEntry = aTooltipConfigArray.trim().split("=");
        -                String key = configEntry[0].trim();
        -                String value;
        +                String configKey = configEntry[0].trim();
        +                String configValue;
                         if (configEntry.length > 1) {
        -                    value = configEntry[1].trim();
        -                    tooltipConfig.put(key, value);
        +                    configValue = configEntry[1].trim();
        +                    result.put(configKey, configValue);
                         } else {
        -                    LOG.warn("component {} tooltip config param {} has no value defined, skipped", component, key);
        +                    LOG.warn("component {} tooltip config param {} has no value defined, skipped", component, configKey);
                         }
                     }
                 }
                 if (component.javascriptTooltip != null)
        -            tooltipConfig.put("jsTooltipEnabled", component.javascriptTooltip);
        +            result.put("jsTooltipEnabled", component.javascriptTooltip);
                 if (component.tooltipIconPath != null)
        -            tooltipConfig.put("tooltipIcon", component.tooltipIconPath);
        +            result.put("tooltipIcon", component.tooltipIconPath);
                 if (component.tooltipDelay != null)
        -            tooltipConfig.put("tooltipDelay", component.tooltipDelay);
        -        return tooltipConfig;
        +            result.put("tooltipDelay", component.tooltipDelay);
        +        return result;
             }
         
             /**
        @@ -995,16 +1047,16 @@ protected void populateComponentHtmlId(Form form) {
                 String generatedId;
                 if (id != null) {
                     // this check is needed for backwards compatibility with 2.1.x
        -            tryId = findStringIfAltSyntax(id);
        +            tryId = findString(id);
                 } else if (null == (generatedId = escape(name != null ? findString(name) : null))) {
                     LOG.debug("Cannot determine id attribute for [{}], consider defining id, name or key attribute!", this);
                     tryId = null;
                 } else if (form != null) {
        -            tryId = form.getParameters().get("id") + "_" + generatedId;
        +            tryId = form.getAttributes().get("id") + "_" + generatedId;
                 } else {
                     tryId = generatedId;
                 }
        -        
        +
                 //fix for https://issues.apache.org/jira/browse/WW-4299
                 //do not assign value to id if tryId is null
                 if (tryId != null) {
        @@ -1023,9 +1075,7 @@ public String getId() {
         
             @StrutsTagAttribute(description="HTML id attribute")
             public void setId(String id) {
        -        if (id != null) {
        -            this.id = findString(id);
        -        }
        +        this.id = id;
             }
         
             @StrutsTagAttribute(description="The template directory.")
        @@ -1052,11 +1102,6 @@ public void setCssClass(String cssClass) {
                 this.cssClass = cssClass;
             }
         
        -    @StrutsTagAttribute(description="The css class to use for element - it's an alias of cssClass attribute.")
        -    public void setClass(String cssClass) {
        -        this.cssClass = cssClass;
        -    }
        -
             @StrutsTagAttribute(description="The css style definitions for element to use")
             public void setCssStyle(String cssStyle) {
                 this.cssStyle = cssStyle;
        @@ -1098,7 +1143,7 @@ public void setLabelSeparator(String labelseparator) {
             }
         
             @StrutsTagAttribute(description="Define label position of form element (top/left)")
        -    public void setLabelposition(String labelPosition) {
        +    public void setLabelPosition(String labelPosition) {
                 this.labelPosition = labelPosition;
             }
         
        @@ -1111,9 +1156,16 @@ public void setRequiredPosition(String requiredPosition) {
             public void setErrorPosition(String errorPosition) {
                 this.errorPosition = errorPosition;
             }
        -    
        +
             @StrutsTagAttribute(description="The name to set for element")
             public void setName(String name) {
        +        if (name != null && name.startsWith("$")) {
        +            LOG.error("The name attribute should not usually be a templating variable." +
        +                      " This can cause a critical vulnerability if the resolved value is derived from user input." +
        +                      " If you are certain that you require this behaviour, please use OGNL expression syntax ( %{expr} ) instead.",
        +                    new IllegalStateException());
        +            return;
        +        }
                 this.name = name;
             }
         
        @@ -1208,11 +1260,13 @@ public void setAccesskey(String accesskey) {
             }
         
             @StrutsTagAttribute(description="Set the tooltip of this particular component")
        +    @Deprecated(since = "7.0.1", forRemoval = true)
             public void setTooltip(String tooltip) {
                 this.tooltip = tooltip;
             }
         
             @StrutsTagAttribute(description="Deprecated. Use individual tooltip configuration attributes instead.")
        +    @Deprecated(since = "7.0.1", forRemoval = true)
             public void setTooltipConfig(String tooltipConfig) {
                 this.tooltipConfig = tooltipConfig;
             }
        @@ -1223,48 +1277,70 @@ public void setKey(String key) {
             }
         
             @StrutsTagAttribute(description="Use JavaScript to generate tooltips", type="Boolean", defaultValue="false")
        +    @Deprecated(since = "7.0.1", forRemoval = true)
             public void setJavascriptTooltip(String javascriptTooltip) {
                 this.javascriptTooltip = javascriptTooltip;
             }
         
             @StrutsTagAttribute(description="CSS class applied to JavaScrip tooltips", defaultValue="StrutsTTClassic")
        +    @Deprecated(since = "7.0.1", forRemoval = true)
             public void setTooltipCssClass(String tooltipCssClass) {
                 this.tooltipCssClass = tooltipCssClass;
             }
         
             @StrutsTagAttribute(description="Delay in milliseconds, before showing JavaScript tooltips ",
                 defaultValue="Classic")
        +    @Deprecated(since = "7.0.1", forRemoval = true)
             public void setTooltipDelay(String tooltipDelay) {
                 this.tooltipDelay = tooltipDelay;
             }
         
             @StrutsTagAttribute(description="Icon path used for image that will have the tooltip")
        +    @Deprecated(since = "7.0.1", forRemoval = true)
             public void setTooltipIconPath(String tooltipIconPath) {
                 this.tooltipIconPath = tooltipIconPath;
             }
         
        -	public void setDynamicAttributes(Map tagDynamicAttributes) {
        -        for (String key : tagDynamicAttributes.keySet()) {
        -            if (!isValidTagAttribute(key)) {
        -                dynamicAttributes.put(key, tagDynamicAttributes.get(key));
        +    public void setDynamicAttributes(Map tagDynamicAttributes) {
        +        for (Map.Entry entry : tagDynamicAttributes.entrySet()) {
        +            String attrName = entry.getKey();
        +            String attrValue = entry.getValue();
        +
        +            if (!isValidTagAttribute(attrName)) {
        +                if (ComponentUtils.containsExpression(attrValue) && !lazyEvaluation()) {
        +                    String translated = TextParseUtil.translateVariables('%', attrValue, stack);
        +                    dynamicAttributes.put(attrName, ObjectUtils.defaultIfNull(translated, attrValue));
        +                } else {
        +                    dynamicAttributes.put(attrName, attrValue);
        +                }
                     }
                 }
             }
         
        -	@Override
        -	/**
        -	 * supports dynamic attributes for freemarker ui tags
        -	 * @see https://issues.apache.org/jira/browse/WW-3174
        -     * @see https://issues.apache.org/jira/browse/WW-4166
        -	 */
        -    public void copyParams(Map params) {
        -        super.copyParams(params);
        -        for (Object o : params.entrySet()) {
        -            Map.Entry entry = (Map.Entry) o;
        -            String key = (String) entry.getKey();
        -            if(!isValidTagAttribute(key) && !key.equals("dynamicAttributes"))
        -                dynamicAttributes.put(key, entry.getValue());
        +    /**
        +     * supports dynamic attributes for freemarker ui tags
        +     * @see WW-3174
        +     * @see WW-4166
        +     */
        +    @Override
        +    public void copyAttributes(Map attributesToCopy) {
        +        super.copyAttributes(attributesToCopy);
        +        for (Map.Entryentry : attributesToCopy.entrySet()) {
        +            String entryKey = entry.getKey();
        +            if (!isValidTagAttribute(entryKey) && !entryKey.equals("dynamicAttributes")) {
        +                dynamicAttributes.put(entryKey, entry.getValue());
        +            }
                 }
             }
         
        +    /**
        +     * Used to avoid evaluating attributes in {@link #evaluateParams()} or {@link #evaluateExtraParams()}
        +     * as evaluation will happen in tag's template
        +     *
        +     * @return boolean false if evaluation should be performed in ftl
        +     */
        +    protected boolean lazyEvaluation() {
        +        return false;
        +    }
        +
         }
        diff --git a/core/src/main/java/org/apache/struts2/components/URL.java b/core/src/main/java/org/apache/struts2/components/URL.java
        index 6269271573..517aabaf62 100644
        --- a/core/src/main/java/org/apache/struts2/components/URL.java
        +++ b/core/src/main/java/org/apache/struts2/components/URL.java
        @@ -1,6 +1,4 @@
         /*
        - * $Id$
        - *
          * Licensed to the Apache Software Foundation (ASF) under one
          * or more contributor license agreements.  See the NOTICE file
          * distributed with this work for additional information
        @@ -18,17 +16,16 @@
          * specific language governing permissions and limitations
          * under the License.
          */
        -
         package org.apache.struts2.components;
         
        -import com.opensymphony.xwork2.inject.Inject;
        -import com.opensymphony.xwork2.util.ValueStack;
        +import org.apache.struts2.inject.Inject;
        +import org.apache.struts2.util.ValueStack;
        +import jakarta.servlet.http.HttpServletRequest;
        +import jakarta.servlet.http.HttpServletResponse;
         import org.apache.struts2.StrutsConstants;
         import org.apache.struts2.views.annotations.StrutsTag;
         import org.apache.struts2.views.annotations.StrutsTagAttribute;
         
        -import javax.servlet.http.HttpServletRequest;
        -import javax.servlet.http.HttpServletResponse;
         import java.io.Writer;
         
         /**
        @@ -109,12 +106,12 @@
         @StrutsTag(name="url", tldTagClass="org.apache.struts2.views.jsp.URLTag", description="This tag is used to create a URL")
         public class URL extends ContextBean {
         
        -    private UrlProvider urlProvider;
        +    private final UrlProvider urlProvider;
             private UrlRenderer urlRenderer;
         
             public URL(ValueStack stack, HttpServletRequest req, HttpServletResponse res) {
                 super(stack);
        -        urlProvider = new ComponentUrlProvider(this, this.parameters);
        +        urlProvider = new ComponentUrlProvider(this, this.attributes);
                 urlProvider.setHttpServletRequest(req);
                 urlProvider.setHttpServletResponse(res);
             }
        diff --git a/core/src/main/java/org/apache/struts2/components/UpDownSelect.java b/core/src/main/java/org/apache/struts2/components/UpDownSelect.java
        index 1529cfd45a..12ab3c46cd 100644
        --- a/core/src/main/java/org/apache/struts2/components/UpDownSelect.java
        +++ b/core/src/main/java/org/apache/struts2/components/UpDownSelect.java
        @@ -1,6 +1,4 @@
         /*
        - * $Id$
        - *
          * Licensed to the Apache Software Foundation (ASF) under one
          * or more contributor license agreements.  See the NOTICE file
          * distributed with this work for additional information
        @@ -18,18 +16,17 @@
          * specific language governing permissions and limitations
          * under the License.
          */
        -
         package org.apache.struts2.components;
         
        -import com.opensymphony.xwork2.util.ValueStack;
        +import org.apache.struts2.util.ValueStack;
        +import jakarta.servlet.http.HttpServletRequest;
        +import jakarta.servlet.http.HttpServletResponse;
         import org.apache.commons.lang3.StringUtils;
         import org.apache.logging.log4j.LogManager;
         import org.apache.logging.log4j.Logger;
         import org.apache.struts2.views.annotations.StrutsTag;
         import org.apache.struts2.views.annotations.StrutsTagAttribute;
         
        -import javax.servlet.http.HttpServletRequest;
        -import javax.servlet.http.HttpServletResponse;
         import java.util.LinkedHashMap;
         import java.util.Map;
         
        @@ -73,7 +70,7 @@
          * {@literal @}s.tag name="updownselect" tld-body-content="JSP" tld-tag-class="org.apache.struts2.views.jsp.ui.UpDownSelectTag"
          * description="Render a up down select element"
          */
        -@StrutsTag(name="updownselect", tldTagClass="org.apache.struts2.views.jsp.ui.UpDownSelectTag", 
        +@StrutsTag(name="updownselect", tldTagClass="org.apache.struts2.views.jsp.ui.UpDownSelectTag",
                 description="Create a Select component with buttons to move the elements in the select component up and down")
         public class UpDownSelect extends Select {
         
        @@ -139,17 +136,17 @@ public void evaluateParams() {
                     // inform form ancestor that we are using a custom onSubmit
                     enableAncestorFormCustomOnsubmit();
         
        -            Map m = (Map) ancestorForm.getParameters().get("updownselectIds");
        +            Map m = (Map) ancestorForm.getAttributes().get("updownselectIds");
                     if (m == null) {
                         // map with key -> id ,  value -> headerKey
                         m = new LinkedHashMap();
                     }
        -            m.put(getParameters().get("id"), getParameters().get("headerKey"));
        -            ancestorForm.getParameters().put("updownselectIds", m);
        +            m.put(getAttributes().get("id"), getAttributes().get("headerKey"));
        +            ancestorForm.getAttributes().put("updownselectIds", m);
                 }
                 else {
                     if (LOG.isWarnEnabled()) {
        -        	LOG.warn("no ancestor form found for updownselect "+this+", therefore autoselect of all elements upon form submission will not work ");
        +                LOG.warn("no ancestor form found for updownselect {}, therefore autoselect of all elements upon form submission will not work ", this);
                     }
                 }
             }
        diff --git a/core/src/main/java/org/apache/struts2/components/UrlProvider.java b/core/src/main/java/org/apache/struts2/components/UrlProvider.java
        index 16da4785d7..477a8b6c26 100644
        --- a/core/src/main/java/org/apache/struts2/components/UrlProvider.java
        +++ b/core/src/main/java/org/apache/struts2/components/UrlProvider.java
        @@ -1,6 +1,4 @@
         /*
        - * $Id$
        - *
          * Licensed to the Apache Software Foundation (ASF) under one
          * or more contributor license agreements.  See the NOTICE file
          * distributed with this work for additional information
        @@ -20,14 +18,14 @@
          */
         package org.apache.struts2.components;
         
        -import com.opensymphony.xwork2.util.ValueStack;
        +import org.apache.struts2.util.ValueStack;
         
        -import javax.servlet.http.HttpServletRequest;
        -import javax.servlet.http.HttpServletResponse;
        +import jakarta.servlet.http.HttpServletRequest;
        +import jakarta.servlet.http.HttpServletResponse;
         import java.util.Map;
         
         /**
        - * Implemntations of this interface can be used to build a URL
        + * Implementations of this interface can be used to build a URL
          */
         public interface UrlProvider {
             /**
        @@ -39,9 +37,9 @@ public interface UrlProvider {
              * get  - include only GET parameters in the URL (default)
              * all  - include both GET and POST parameters in the URL
              */
        -    public static final String NONE = "none";
        -    public static final String GET = "get";
        -    public static final String ALL = "all";
        +    String NONE = "none";
        +    String GET = "get";
        +    String ALL = "all";
         
             boolean isPutInContext();
         
        @@ -57,7 +55,7 @@ public interface UrlProvider {
         
             String getIncludeParams();
         
        -    Map getParameters();
        +    Map getParameters();
         
             HttpServletRequest getHttpServletRequest();
         
        @@ -80,19 +78,19 @@ public interface UrlProvider {
             boolean isForceAddSchemeHostAndPort();
         
             boolean isEscapeAmp();
        -    
        +
             String getPortletMode();
        -    
        +
             String getWindowState();
         
        -    String determineActionURL(String action, String namespace, String method, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Map parameters, String scheme, boolean includeContext, boolean encode, boolean forceAddSchemeHostAndPort, boolean escapeAmp);
        -    
        +    String determineActionURL(String action, String namespace, String method, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Map parameters, String scheme, boolean includeContext, boolean encode, boolean forceAddSchemeHostAndPort, boolean escapeAmp);
        +
             String determineNamespace(String namespace, ValueStack stack, HttpServletRequest req);
         
             String getAnchor();
        -    
        +
             String getPortletUrlType();
        -    
        +
             ValueStack getStack();
         
             void setUrlIncludeParams(String urlIncludeParams);
        diff --git a/core/src/main/java/org/apache/struts2/components/UrlRenderer.java b/core/src/main/java/org/apache/struts2/components/UrlRenderer.java
        index 389fb39a5c..9a069e8a91 100644
        --- a/core/src/main/java/org/apache/struts2/components/UrlRenderer.java
        +++ b/core/src/main/java/org/apache/struts2/components/UrlRenderer.java
        @@ -1,6 +1,4 @@
         /*
        - * $Id$
        - *
          * Licensed to the Apache Software Foundation (ASF) under one
          * or more contributor license agreements.  See the NOTICE file
          * distributed with this work for additional information
        @@ -18,7 +16,6 @@
          * specific language governing permissions and limitations
          * under the License.
          */
        -
         package org.apache.struts2.components;
         
         import org.apache.struts2.dispatcher.mapper.ActionMapper;
        @@ -27,30 +24,30 @@
         
         /**
          * Implementations of this interface are responsible for rendering/creating URLs for a specific
        - * environment (e.g. Servlet, Portlet). 
        + * environment (e.g. Servlet). 
          *
          */
         public interface UrlRenderer {
        -	
        -	/**
        -	 * Preprocessing step
        -	 * @param provider The {@link UrlProvider} component that "owns" this renderer.
        -	 */
        -	void beforeRenderUrl(UrlProvider provider);
        -	
        -	/**
        -	 * Render a URL.
        -	 * @param writer A writer that the implementation can use to write the result to.
        -	 * @param provider The {@link UrlProvider} component that "owns" this renderer.
        -	 */
        -	void renderUrl(Writer writer, UrlProvider provider);
        -	
        -	/**
        -	 * Render a Form URL.
        -	 * @param formComponent The {@link Form} component that "owns" this renderer.
        -	 */
        -	void renderFormUrl(Form formComponent);
        -
        -      void setActionMapper(ActionMapper actionMapper);
        +
        +    /**
        +     * Preprocessing step
        +     * @param provider The {@link UrlProvider} component that "owns" this renderer.
        +     */
        +    void beforeRenderUrl(UrlProvider provider);
        +
        +    /**
        +     * Render a URL.
        +     * @param writer A writer that the implementation can use to write the result to.
        +     * @param provider The {@link UrlProvider} component that "owns" this renderer.
        +     */
        +    void renderUrl(Writer writer, UrlProvider provider);
        +
        +    /**
        +     * Render a Form URL.
        +     * @param formComponent The {@link Form} component that "owns" this renderer.
        +     */
        +    void renderFormUrl(Form formComponent);
        +
        +    void setActionMapper(ActionMapper actionMapper);
         
         }
        diff --git a/core/src/main/java/org/apache/struts2/components/date/DateFormatter.java b/core/src/main/java/org/apache/struts2/components/date/DateFormatter.java
        new file mode 100644
        index 0000000000..282daaa061
        --- /dev/null
        +++ b/core/src/main/java/org/apache/struts2/components/date/DateFormatter.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.struts2.components.date;
        +
        +import java.time.temporal.TemporalAccessor;
        +
        +/**
        + * Allows defines a wrapper around different formatting APIs, like old SimpleDateFormat
        + * and new DateTimeFormatter introduced in Java 8 Date/Time API
        + * 

        + * New instance will be injected using {@link org.apache.struts2.StrutsConstants#STRUTS_DATE_FORMATTER} + */ +public interface DateFormatter { + + /** + * Formats provided temporal with the given format + * + * @param temporal Java 8 {@link TemporalAccessor} + * @param format implementation specific format + * @return a string representation of the formatted `temporal` + */ + String format(TemporalAccessor temporal, String format); + +} diff --git a/core/src/main/java/org/apache/struts2/components/date/DateTimeFormatterAdapter.java b/core/src/main/java/org/apache/struts2/components/date/DateTimeFormatterAdapter.java new file mode 100644 index 0000000000..f68236414b --- /dev/null +++ b/core/src/main/java/org/apache/struts2/components/date/DateTimeFormatterAdapter.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.struts2.components.date; + +import org.apache.struts2.ActionContext; + +import java.time.format.DateTimeFormatter; +import java.time.format.FormatStyle; +import java.time.temporal.TemporalAccessor; +import java.util.Locale; + +public class DateTimeFormatterAdapter implements DateFormatter { + + @Override + public String format(TemporalAccessor temporal, String format) { + DateTimeFormatter dtf; + Locale locale = ActionContext.getContext().getLocale(); + if (format == null) { + dtf = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM) + .withLocale(locale); + } else { + dtf = DateTimeFormatter.ofPattern(format, locale); + } + return dtf.format(temporal); + } + +} diff --git a/core/src/main/java/org/apache/struts2/components/date/SimpleDateFormatAdapter.java b/core/src/main/java/org/apache/struts2/components/date/SimpleDateFormatAdapter.java new file mode 100644 index 0000000000..8babfca475 --- /dev/null +++ b/core/src/main/java/org/apache/struts2/components/date/SimpleDateFormatAdapter.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.struts2.components.date; + +import org.apache.struts2.ActionContext; + +import java.text.DateFormat; +import java.text.SimpleDateFormat; +import java.time.Instant; +import java.time.temporal.TemporalAccessor; +import java.util.Date; +import java.util.Locale; + +public class SimpleDateFormatAdapter implements DateFormatter { + + @Override + public String format(TemporalAccessor temporal, String format) { + DateFormat df; + Locale locale = ActionContext.getContext().getLocale(); + if (format == null) { + df = DateFormat.getDateTimeInstance(DateFormat.MEDIUM, DateFormat.MEDIUM, locale); + } else { + df = new SimpleDateFormat(format, locale); + } + return df.format(new Date(Instant.from(temporal).toEpochMilli())); + } + +} diff --git a/core/src/main/java/org/apache/struts2/components/template/BaseTemplateEngine.java b/core/src/main/java/org/apache/struts2/components/template/BaseTemplateEngine.java index 59e5aacf24..9ebcd116d1 100644 --- a/core/src/main/java/org/apache/struts2/components/template/BaseTemplateEngine.java +++ b/core/src/main/java/org/apache/struts2/components/template/BaseTemplateEngine.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,15 +16,14 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components.template; -import com.opensymphony.xwork2.util.ClassLoaderUtil; +import org.apache.struts2.util.ClassLoaderUtil; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.ServletActionContext; -import javax.servlet.ServletContext; +import jakarta.servlet.ServletContext; import java.io.*; import java.util.Map; import java.util.Properties; @@ -145,7 +142,7 @@ private InputStream createFileInputStream(File propFile) throws FileNotFoundExce protected String getFinalTemplateName(Template template) { String t = template.toString(); - if (t.indexOf(".") <= 0) { + if (t.indexOf('.') <= 0) { return t + "." + getSuffix(); } return t; diff --git a/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java b/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java index 67a332ca27..99c1d4797f 100644 --- a/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java +++ b/core/src/main/java/org/apache/struts2/components/template/FreemarkerTemplateEngine.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,29 +16,26 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components.template; -import com.opensymphony.xwork2.ActionContext; -import com.opensymphony.xwork2.ActionInvocation; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ClassLoaderUtil; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.ActionContext; +import org.apache.struts2.ActionInvocation; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ClassLoaderUtil; +import org.apache.struts2.util.ValueStack; import freemarker.core.ParseException; import freemarker.template.Configuration; import freemarker.template.SimpleHash; +import jakarta.servlet.ServletContext; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import org.apache.struts2.ServletActionContext; import org.apache.struts2.views.freemarker.FreemarkerManager; -import javax.servlet.ServletContext; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; import java.io.IOException; import java.io.Writer; import java.util.List; -import java.util.Map; /** * Freemarker based template engine. @@ -51,7 +46,7 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine { static { try { - bodyContent = ClassLoaderUtil.loadClass("javax.servlet.jsp.tagext.BodyContent", + bodyContent = ClassLoaderUtil.loadClass("jakarta.servlet.jsp.tagext.BodyContent", FreemarkerTemplateEngine.class); } catch (ClassNotFoundException e) { // this is OK -- this just means JSP isn't even being used here, which is perfectly fine. @@ -67,14 +62,14 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine { public void setFreemarkerManager(FreemarkerManager mgr) { this.freemarkerManager = mgr; } - + public void renderTemplate(TemplateRenderingContext templateContext) throws Exception { // get the various items required from the stack ValueStack stack = templateContext.getStack(); - Map context = stack.getContext(); - ServletContext servletContext = (ServletContext) context.get(ServletActionContext.SERVLET_CONTEXT); - HttpServletRequest req = (HttpServletRequest) context.get(ServletActionContext.HTTP_REQUEST); - HttpServletResponse res = (HttpServletResponse) context.get(ServletActionContext.HTTP_RESPONSE); + ActionContext context = stack.getActionContext(); + ServletContext servletContext = context.getServletContext(); + HttpServletRequest req = context.getServletRequest(); + HttpServletResponse res = context.getServletResponse(); // prepare freemarker Configuration config = freemarkerManager.getConfiguration(servletContext); @@ -124,6 +119,10 @@ public void renderTemplate(TemplateRenderingContext templateContext) throws Exce ActionInvocation ai = ActionContext.getContext().getActionInvocation(); Object action = (ai == null) ? null : ai.getAction(); + if (action == null) { + LOG.warn("Rendering tag {} out of Action scope, accessing directly JSPs is not recommended! " + + "Please read https://struts.apache.org/security/#never-expose-jsp-files-directly", templateName); + } SimpleHash model = freemarkerManager.buildTemplateModel(stack, action, servletContext, req, res, config.getObjectWrapper()); model.put("tag", templateContext.getTag()); @@ -134,7 +133,7 @@ public void renderTemplate(TemplateRenderingContext templateContext) throws Exce Writer writer = templateContext.getWriter(); final Writer wrapped = writer; writer = new Writer() { - public void write(char cbuf[], int off, int len) throws IOException { + public void write(char[] cbuf, int off, int len) throws IOException { wrapped.write(cbuf, off, len); } @@ -147,10 +146,12 @@ public void close() throws IOException { } }; + LOG.debug("Push tag on top of the stack"); + stack.push(templateContext.getTag()); try { - stack.push(templateContext.getTag()); template.process(model, writer); } finally { + LOG.debug("Removes tag from top of the stack"); stack.pop(); } } @@ -158,4 +159,4 @@ public void close() throws IOException { protected String getSuffix() { return "ftl"; } -} \ No newline at end of file +} diff --git a/core/src/main/java/org/apache/struts2/components/template/JspTemplateEngine.java b/core/src/main/java/org/apache/struts2/components/template/JspTemplateEngine.java index 077e70de9e..790f3d8591 100644 --- a/core/src/main/java/org/apache/struts2/components/template/JspTemplateEngine.java +++ b/core/src/main/java/org/apache/struts2/components/template/JspTemplateEngine.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,11 +16,12 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components.template; -import com.opensymphony.xwork2.inject.Inject; -import com.opensymphony.xwork2.util.ValueStack; +import org.apache.struts2.inject.Inject; +import org.apache.struts2.util.ValueStack; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.servlet.jsp.PageContext; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; import org.apache.struts2.ServletActionContext; @@ -30,8 +29,6 @@ import org.apache.struts2.components.Include; import org.apache.struts2.components.UIBean; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.jsp.PageContext; import java.util.List; /** @@ -47,6 +44,7 @@ public void setEncoding(String encoding) { this.encoding = encoding; } + @Override public void renderTemplate(TemplateRenderingContext templateContext) throws Exception { Template template = templateContext.getTemplate(); @@ -84,6 +82,7 @@ public void renderTemplate(TemplateRenderingContext templateContext) throws Exce stack.pop(); } + @Override protected String getSuffix() { return "jsp"; } diff --git a/core/src/main/java/org/apache/struts2/components/template/Template.java b/core/src/main/java/org/apache/struts2/components/template/Template.java index 40c30fcc0a..f3a47f226a 100644 --- a/core/src/main/java/org/apache/struts2/components/template/Template.java +++ b/core/src/main/java/org/apache/struts2/components/template/Template.java @@ -1,6 +1,4 @@ /* - * $Id$ - * * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file * distributed with this work for additional information @@ -18,11 +16,11 @@ * specific language governing permissions and limitations * under the License. */ - package org.apache.struts2.components.template; import java.util.ArrayList; import java.util.List; +import java.util.Objects; /** *

        @@ -61,7 +59,7 @@ public String getName() { } public List