mirror of
https://github.com/apache/struts.git
synced 2026-08-08 08:07:17 +00:00
Compare commits
234 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 18a72c3dff | |||
| 6ea50122d6 | |||
| ea7fba2846 | |||
| 4ab427f2f2 | |||
| 0a30eb44e6 | |||
| 138a8d74f0 | |||
| 341a8f20e0 | |||
| 9a431ea470 | |||
| 0fe27a673d | |||
| 35a50ea836 | |||
| 927c58b7d3 | |||
| ac168968a0 | |||
| 5a30cdbede | |||
| bfcc0b5898 | |||
| 4a51aacf40 | |||
| 728edbef56 | |||
| 6135a71335 | |||
| 6330bb1ce3 | |||
| 4a585347ed | |||
| 4bb81d5909 | |||
| 054f1f4cdb | |||
| 79a84a8f02 | |||
| 2660aaec56 | |||
| 34aeeded55 | |||
| 8d2d996056 | |||
| 6658c6360e | |||
| 9c078aef14 | |||
| eb51594ed3 | |||
| b536136191 | |||
| c74287f741 | |||
| 9e7e0b395d | |||
| 784293e46f | |||
| 58dcc830ea | |||
| 936481e7ea | |||
| a02cc6507c | |||
| 084c257d6e | |||
| 94a0c6e425 | |||
| 3e30d0c375 | |||
| 9568888700 | |||
| 943cb62953 | |||
| 79d6c07a57 | |||
| 7064c53f5c | |||
| 3fdb918127 | |||
| 1069cf8c09 | |||
| c41f05fe68 | |||
| 993c4c4cab | |||
| 01164c4d74 | |||
| 738d27952f | |||
| 984f8eff2e | |||
| 802afb0cc0 | |||
| 339c30320a | |||
| a562f8f806 | |||
| ac13c32bdb | |||
| bb71610296 | |||
| 3d7f66f428 | |||
| 50842e8d19 | |||
| cca986df35 | |||
| 511ec62105 | |||
| 2cb0d28960 | |||
| e783d18715 | |||
| 864f513365 | |||
| 9dd2560172 | |||
| 415e0fbd44 | |||
| 26effbf05d | |||
| 4c8cc361d5 | |||
| a21bd994eb | |||
| 8f0db1d22a | |||
| 58f287bf4a | |||
| e0da03c262 | |||
| 04cf1dae5f | |||
| 5338b44c23 | |||
| 2217e2c1ca | |||
| cbfd3a7ab9 | |||
| 097297affd | |||
| ddfaa1683c | |||
| ddbd02e6bb | |||
| 6887ef900b | |||
| 326de812ac | |||
| 32201b2ef2 | |||
| a4fe51f5b3 | |||
| 3774ffa7c3 | |||
| cf2078d1de | |||
| 7183d32caf | |||
| e0e7e3cb20 | |||
| eb68368280 | |||
| 296b3cc89c | |||
| 9fb86054bb | |||
| 0fc71949ca | |||
| 9faa002fa7 | |||
| 88bc5c6802 | |||
| dc1a663d69 | |||
| 36ac23acf5 | |||
| 6b2cc20b2d | |||
| ab22c7377d | |||
| 062b76718b | |||
| dc5dac7be2 | |||
| 6334a3e19e | |||
| 858f19557d | |||
| d97fa1eb38 | |||
| b9cd7d8159 | |||
| 03edeee0d8 | |||
| f04b68db03 | |||
| 7b655207ec | |||
| c9c39130f6 | |||
| 12beb20949 | |||
| a5899726a0 | |||
| 22a80f9c51 | |||
| 854572905e | |||
| b40f3efc74 | |||
| 980387e91c | |||
| 5a3d2c4eb9 | |||
| 8514406142 | |||
| bbb5b6bb37 | |||
| ce2975e2f0 | |||
| 49240c50a2 | |||
| 941d88d115 | |||
| 8c4a90f6e3 | |||
| 16c2948f1a | |||
| 58a76162a6 | |||
| b5e802174a | |||
| cdb70e6bed | |||
| 1380802b75 | |||
| 253d8558e5 | |||
| a97ee9e9cb | |||
| 23969abc19 | |||
| 2707bf0489 | |||
| 74d4e23716 | |||
| 2a03047e9e | |||
| b1c1be6e40 | |||
| 6536dc65d8 | |||
| 915386816b | |||
| 80c2de9e92 | |||
| b62e583646 | |||
| 8b359383a1 | |||
| 11e716f979 | |||
| 71c7064f29 | |||
| 09472808aa | |||
| d119ba8e13 | |||
| 86b45e96fc | |||
| 3c9465b857 | |||
| 0c73cf2e05 | |||
| 6785997412 | |||
| 5a7fce066f | |||
| 4fbada4cd9 | |||
| 15bbf0ef1d | |||
| 3119eb65db | |||
| de3dabbe44 | |||
| 82f7904206 | |||
| 42e3da550f | |||
| f3cb89202d | |||
| 836a27692e | |||
| 6312572331 | |||
| e7db7ade62 | |||
| b77c2f476a | |||
| e6c1cec7f8 | |||
| a781b5a27b | |||
| b71732fa14 | |||
| 3f79d64e6a | |||
| 039fd9f4ee | |||
| 393d5be50c | |||
| 24e279b165 | |||
| cb59974903 | |||
| ecfdee137d | |||
| 8c37b1523f | |||
| 62b83021a2 | |||
| f3f2d52a1c | |||
| 61ded9a3e7 | |||
| 963b473e6c | |||
| d639b59f6d | |||
| 8e468a368e | |||
| ebe1b80ed2 | |||
| 957292ecdb | |||
| 06290cef91 | |||
| a6a4529503 | |||
| 64d054221f | |||
| dc4e403d30 | |||
| e6bc93daf2 | |||
| 0e4d5962e1 | |||
| 69102e9075 | |||
| 1c2b491a27 | |||
| 5af840b160 | |||
| b6b74a46ea | |||
| fc2aebd10a | |||
| ba041e1ee6 | |||
| 0c3534e8b4 | |||
| 9a2996f9b7 | |||
| 3825229f44 | |||
| 584634a9b5 | |||
| 5763476830 | |||
| 105b22fb9a | |||
| 4b3ee53f93 | |||
| 68fb49c10e | |||
| 77c175c7be | |||
| 65b7e8c36f | |||
| 735bbc283e | |||
| 981885fd6a | |||
| 07b88fcc35 | |||
| 2cbe47297e | |||
| 545add9365 | |||
| ebecc7d39d | |||
| 226a1d49ce | |||
| 075ef7c4e1 | |||
| 1237110652 | |||
| 3f2518afa8 | |||
| 9f9edf4705 | |||
| 7e912742ed | |||
| c98b60cd9a | |||
| 5ae9688ae8 | |||
| b72200aabf | |||
| 16e7c9b459 | |||
| bea1c6f09f | |||
| 888884cc51 | |||
| b387abae01 | |||
| 059a2a6117 | |||
| c0a3be9fd8 | |||
| 4a7cae029a | |||
| 9873a7f56b | |||
| 086b514d59 | |||
| 6024dd6fa4 | |||
| 4eb2ee8384 | |||
| 8e49362bf8 | |||
| 7541d9ab35 | |||
| c82fdb5e76 | |||
| f40f9f15e5 | |||
| 2d9cdb73a5 | |||
| d07a496d5c | |||
| bef1f67d4a | |||
| e2718aa482 | |||
| b73fec4de0 | |||
| c2795d2e30 | |||
| a987e31a0e | |||
| 6aff5b7faa | |||
| 5b40f9f48e | |||
| e9d0a5518c |
@@ -1,3 +1,4 @@
|
||||
# Documentation https://s.apache.org/asfyaml
|
||||
notifications:
|
||||
commits: commits@struts.apache.org
|
||||
# Send all issue emails (new, closed, comments) to issues@
|
||||
@@ -8,3 +9,8 @@ notifications:
|
||||
pullrequests_comment: issues@struts.apache.org
|
||||
# Link opened PRs with JIRA
|
||||
jira_options: link label worklog
|
||||
|
||||
github:
|
||||
del_branch_on_merge: true
|
||||
protected_branches:
|
||||
master: { }
|
||||
|
||||
@@ -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: "CodeQL"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ "master" ]
|
||||
pull_request:
|
||||
|
||||
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@v3
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
languages: ${{ matrix.language }}
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
with:
|
||||
category: "/language:${{matrix.language}}"
|
||||
@@ -0,0 +1,57 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
|
||||
name: Java Build
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
env:
|
||||
MAVEN_OPTS: -Xmx2048m -Xms1024m
|
||||
LANG: en_US.utf8
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
java: [ '8', '11', '17' ]
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v3.0.2
|
||||
- name: Set up cache
|
||||
uses: actions/cache@v3.0.8
|
||||
with:
|
||||
path: ~/.m2/repository
|
||||
key: ${{ runner.os }}-maven-${{ hashFiles('**/pom.xml') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-maven-
|
||||
- name: Set up JDK ${{ matrix.java }}
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
distribution: adopt
|
||||
java-version: ${{ matrix.java }}
|
||||
- name: Build with Maven on Java ${{ matrix.java }}
|
||||
if: matrix.java != '11'
|
||||
run: mvn -B -V -DskipAssembly test --no-transfer-progress
|
||||
- name: Code coverage on Java ${{ matrix.java }}
|
||||
if: matrix.java == '11'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
SONAR_TOKEN: ${{ secrets.SONARCLOUD_TOKEN }}
|
||||
run: mvn -B -V -Pcoverage -DskipAssembly verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar --no-transfer-progress
|
||||
@@ -0,0 +1,69 @@
|
||||
# Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
# contributor license agreements. See the NOTICE file distributed with
|
||||
# this work for additional information regarding copyright ownership.
|
||||
# The ASF licenses this file to You under the Apache license, Version 2.0
|
||||
# (the "License"); you may not use this file except in compliance with
|
||||
# the License. You may obtain a copy of the License at
|
||||
#
|
||||
# http://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT 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: [ "master" ]
|
||||
|
||||
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@93ea575cb5d8a053eaa0ac8fa3b40d7e05a33cc8 # 3.1.0
|
||||
with:
|
||||
persist-credentials: false
|
||||
|
||||
- name: "Run analysis"
|
||||
uses: ossf/scorecard-action@99c53751e09b9529366343771cc321ec74e9bd3d # 2.0.6
|
||||
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@3cea5372237819ed00197afe530f5a7ea3e805c8 # 3.1.0
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
|
||||
- name: "Upload to code-scanning"
|
||||
uses: github/codeql-action/upload-sarif@b398f525a5587552e573b247ac661067fafa920b # 2.1.22
|
||||
with:
|
||||
sarif_file: results.sarif
|
||||
+1
-1
@@ -14,5 +14,5 @@
|
||||
# KIND, either express or implied. See the License for the
|
||||
# specific language governing permissions and limitations
|
||||
# under the License.
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.4/apache-maven-3.8.4-bin.zip
|
||||
distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.8.6/apache-maven-3.8.6-bin.zip
|
||||
wrapperUrl=https://repo.maven.apache.org/maven2/org/apache/maven/wrapper/maven-wrapper/3.1.0/maven-wrapper-3.1.0.jar
|
||||
|
||||
-32
@@ -1,32 +0,0 @@
|
||||
dist: trusty
|
||||
language: java
|
||||
sudo: false
|
||||
|
||||
jdk:
|
||||
- oraclejdk9
|
||||
- oraclejdk11
|
||||
|
||||
install: true
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: iI7IpfDtS+LUyS2yNuRCR3KelNyvBHuoMQ3gb1UNmR5SSL7jO/p3olQWrQROs28FJ+dpE3lHyIjoHrebKQGJHHAgTG2XWxn+G3fDsf+wSSFSLoDGj0o2SgGXooBbR2dccnNZHCyQaOyE2cIPWaOxrQZFE4No70LQB4mrP/gdkoc=
|
||||
matrix:
|
||||
include:
|
||||
- jdk: oraclejdk8
|
||||
env: STRUTS_IT=true # do integration tests and coverage reports when jdk7,9 and 11 tests prospered
|
||||
|
||||
script:
|
||||
- if [ "$STRUTS_IT" == "true" ]; then
|
||||
./mvnw clean verify org.jacoco:jacoco-maven-plugin:report org.jacoco:jacoco-maven-plugin:report-integration org.eluder.coveralls:coveralls-maven-plugin:report -Ptravis-coveralls -DskipAssembly -B;
|
||||
else
|
||||
if [ "$TRAVIS_PULL_REQUEST" != "false" ]; then
|
||||
./mvnw test -DskipAssembly -B;
|
||||
else
|
||||
./mvnw test -DskipAssembly -Dupdate-impact -B;
|
||||
fi;
|
||||
fi;
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.m2
|
||||
Vendored
+13
-11
@@ -39,12 +39,12 @@ pipeline {
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh 'mvn -B clean install -DskipTests -DskipAssembly'
|
||||
sh './mvnw -B clean install -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'mvn -B test'
|
||||
sh './mvnw -B test'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@@ -74,12 +74,12 @@ pipeline {
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh 'mvn -B clean install -DskipTests -DskipAssembly'
|
||||
sh './mvnw -B clean install -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'mvn -B test'
|
||||
sh './mvnw -B verify -Pcoverage -DskipAssembly'
|
||||
}
|
||||
post {
|
||||
always {
|
||||
@@ -94,7 +94,7 @@ pipeline {
|
||||
}
|
||||
steps {
|
||||
withCredentials([string(credentialsId: 'asf-struts-sonarcloud', variable: 'SONARCLOUD_TOKEN')]) {
|
||||
sh 'mvn sonar:sonar -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN}'
|
||||
sh './mvnw -B -Pcoverage -DskipAssembly -Dsonar.login=${SONARCLOUD_TOKEN} verify org.sonarsource.scanner.maven:sonar-maven-plugin:sonar'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -119,12 +119,12 @@ pipeline {
|
||||
stages {
|
||||
stage('Build') {
|
||||
steps {
|
||||
sh 'mvn -B clean install -DskipTests -DskipAssembly'
|
||||
sh './mvnw -B clean install -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Test') {
|
||||
steps {
|
||||
sh 'mvn -B test'
|
||||
sh './mvnw -B test'
|
||||
// step([$class: 'JiraIssueUpdater', issueSelector: [$class: 'DefaultIssueSelector'], scm: scm])
|
||||
}
|
||||
post {
|
||||
@@ -142,7 +142,7 @@ pipeline {
|
||||
dir("local-snapshots-dir/") {
|
||||
deleteDir()
|
||||
}
|
||||
sh 'mvn -B source:jar javadoc:jar -DskipAssembbly'
|
||||
sh './mvnw -B source:jar javadoc:jar -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
stage('Deploy Snapshot') {
|
||||
@@ -151,7 +151,7 @@ pipeline {
|
||||
}
|
||||
steps {
|
||||
withCredentials([file(credentialsId: 'lukaszlenart-repository-access-token', variable: 'CUSTOM_SETTINGS')]) {
|
||||
sh 'mvn -s \${CUSTOM_SETTINGS} deploy'
|
||||
sh './mvnw -s \${CUSTOM_SETTINGS} deploy -DskipTests -DskipAssembly'
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -160,14 +160,16 @@ pipeline {
|
||||
branch 'master'
|
||||
}
|
||||
steps {
|
||||
sh './mvnw -B package -DskipTests'
|
||||
sshPublisher(publishers: [
|
||||
sshPublisherDesc(
|
||||
configName: 'Nightlies',
|
||||
transfers: [
|
||||
sshTransfer(
|
||||
remoteDirectory: '/x1/dist/struts',
|
||||
remoteDirectory: '/struts/snapshot',
|
||||
removePrefix: 'assembly/target/assembly/out',
|
||||
sourceFiles: 'assembly/target/assembly/out/struts-*.zip'
|
||||
sourceFiles: 'assembly/target/assembly/out/struts-*.zip',
|
||||
cleanRemote: true
|
||||
)
|
||||
],
|
||||
verbose: true
|
||||
|
||||
@@ -17,11 +17,13 @@
|
||||
The Apache Struts web framework
|
||||
-------------------------------
|
||||
|
||||
[](https://ci-builds.apache.org/job/Struts/job/Struts%20Core/job/master/)
|
||||
[](https://app.travis-ci.com/apache/struts)
|
||||
[](https://ci-builds.apache.org/job/Struts/job/Struts%20Core/job/master/)
|
||||
[](https://github.com/apache/struts/actions/workflows/maven.yml)
|
||||
[](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/)
|
||||
[](https://javadoc.io/doc/org.apache.struts/struts2-core)
|
||||
[](https://coveralls.io/github/apache/struts)
|
||||
[](https://sonarcloud.io/summary/new_code?id=apache_struts)
|
||||
[](https://deps.dev/maven/org.apache.struts%3Astruts2-core)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/6618)
|
||||
[](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.
|
||||
|
||||
+2
-2
@@ -7,8 +7,8 @@ and what potential vulnerability it can have:
|
||||
|
||||
| Version | Supported |
|
||||
| ------- | ------------------ |
|
||||
| 2.5.20 | :white_check_mark: |
|
||||
| 2.3.37 | :white_check_mark: |
|
||||
| 6.0.0 | :white_check_mark: |
|
||||
| 2.5.30 | :white_check_mark: |
|
||||
|
||||
## Reporting New Security Issues with thr Apache Struts
|
||||
|
||||
|
||||
@@ -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.
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<version>6.1.0</version>
|
||||
</parent>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<version>6.1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-rest-showcase</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<version>6.1.0</version>
|
||||
<name>Struts 2 Rest Showcase Webapp</name>
|
||||
<description>Struts 2 Rest Showcase Example</description>
|
||||
|
||||
@@ -108,9 +108,9 @@
|
||||
<finalName>struts2-rest-showcase</finalName>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>8.1.16.v20140903</version>
|
||||
<version>9.4.46.v20220331</version>
|
||||
<configuration>
|
||||
<stopKey>CTRL+C</stopKey>
|
||||
<stopPort>8999</stopPort>
|
||||
@@ -125,6 +125,7 @@
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine}</argLine>
|
||||
<excludes>
|
||||
<exclude>it/**</exclude>
|
||||
<exclude>**/*$*</exclude>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
|
||||
<struts>
|
||||
@@ -41,4 +41,4 @@
|
||||
<package name="rest-showcase" extends="rest-default">
|
||||
<global-allowed-methods>index,show,create,update,destroy,deleteConfirm,edit,editNew</global-allowed-methods>
|
||||
</package>
|
||||
</struts>
|
||||
</struts>
|
||||
|
||||
@@ -19,13 +19,14 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<web-app id="starter" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
||||
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||
version="3.1">
|
||||
|
||||
<display-name>Struts 2 Rest Example</display-name>
|
||||
|
||||
|
||||
<!-- Filters -->
|
||||
<!-- START SNIPPET: filter -->
|
||||
<filter>
|
||||
|
||||
+21
-25
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<version>6.1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-showcase</artifactId>
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -121,6 +121,11 @@
|
||||
<artifactId>log4j-jcl</artifactId>
|
||||
<version>${log4j2.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.logging.log4j</groupId>
|
||||
<artifactId>log4j-slf4j-impl</artifactId>
|
||||
<version>${log4j2.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>opensymphony</groupId>
|
||||
@@ -144,24 +149,15 @@
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.htmlunit</groupId>
|
||||
<artifactId>htmlunit</artifactId>
|
||||
<version>2.39.0</version>
|
||||
<version>2.61.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- BeanValidation Example -->
|
||||
<dependency>
|
||||
<groupId>org.hibernate</groupId>
|
||||
<groupId>org.hibernate.validator</groupId>
|
||||
<artifactId>hibernate-validator</artifactId>
|
||||
<version>6.1.2.Final</version>
|
||||
</dependency>
|
||||
|
||||
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
|
||||
This is only necessary in tests-->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>test</scope>
|
||||
<version>${hibernate-validator.version}</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
@@ -171,11 +167,14 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-failsafe-plugin</artifactId>
|
||||
<version>3.0.0-M4</version>
|
||||
<version>3.0.0-M6</version>
|
||||
<configuration>
|
||||
<includes>
|
||||
<include>it.org.apache.struts2.showcase.*Test</include>
|
||||
</includes>
|
||||
<systemPropertyVariables>
|
||||
<http.port>8090</http.port>
|
||||
</systemPropertyVariables>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
@@ -193,22 +192,21 @@
|
||||
</executions>
|
||||
</plugin>
|
||||
<plugin>
|
||||
<groupId>org.mortbay.jetty</groupId>
|
||||
<groupId>org.eclipse.jetty</groupId>
|
||||
<artifactId>jetty-maven-plugin</artifactId>
|
||||
<version>8.1.16.v20140903</version>
|
||||
<version>9.4.46.v20220331</version>
|
||||
<configuration>
|
||||
<stopKey>CTRL+C</stopKey>
|
||||
<stopPort>8999</stopPort>
|
||||
<systemProperties>
|
||||
<systemProperty>
|
||||
<name>log4j.configuration</name>
|
||||
<value>file:${basedir}/src/main/resources/log4j.properties</value>
|
||||
</systemProperty>
|
||||
<systemProperty>
|
||||
<name>slf4j</name>
|
||||
<value>false</value>
|
||||
</systemProperty>
|
||||
</systemProperties>
|
||||
<httpConnector>
|
||||
<port>8090</port>
|
||||
</httpConnector>
|
||||
<scanIntervalSeconds>10</scanIntervalSeconds>
|
||||
<webAppSourceDirectory>${basedir}/src/main/webapp/</webAppSourceDirectory>
|
||||
<webAppConfig>
|
||||
@@ -223,11 +221,8 @@
|
||||
<goals>
|
||||
<!-- stop any previous instance to free up the port -->
|
||||
<goal>stop</goal>
|
||||
<goal>run-forked</goal>
|
||||
<goal>start</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<waitForChild>false</waitForChild>
|
||||
</configuration>
|
||||
</execution>
|
||||
<execution>
|
||||
<id>stop-jetty</id>
|
||||
@@ -242,6 +237,7 @@
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine}</argLine>
|
||||
<excludes>
|
||||
<exclude>it/**</exclude>
|
||||
<exclude>**/*$*</exclude>
|
||||
|
||||
+158
-171
@@ -22,16 +22,13 @@ 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.action.ServletContextAware;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
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;
|
||||
@@ -42,202 +39,192 @@ import java.util.List;
|
||||
*/
|
||||
public class ViewSourceAction extends ActionSupport implements ServletContextAware {
|
||||
|
||||
private String page;
|
||||
private String className;
|
||||
private String config;
|
||||
private String page;
|
||||
private String className;
|
||||
private String config;
|
||||
|
||||
private List pageLines;
|
||||
private List classLines;
|
||||
private List configLines;
|
||||
private List<String> pageLines;
|
||||
private List<String> classLines;
|
||||
private List<String> configLines;
|
||||
|
||||
private int configLine;
|
||||
private int padding = 10;
|
||||
private int configLine;
|
||||
private int padding = 10;
|
||||
|
||||
private ServletContext servletContext;
|
||||
private ServletContext servletContext;
|
||||
|
||||
public String execute() throws MalformedURLException, IOException {
|
||||
public String execute() throws IOException {
|
||||
|
||||
if (page != null) {
|
||||
if (page != null) {
|
||||
|
||||
InputStream in = ClassLoaderUtil.getResourceAsStream(page.substring(page.indexOf("//") + 1), getClass());
|
||||
page = page.replace("//", "/");
|
||||
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 = 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 (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 (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 (in != null) {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
|
||||
final String rootPath = ServletActionContext.getServletContext().getRealPath("/");
|
||||
final String rootPathUnix = (rootPath != null ? rootPath.replace(File.separator, "/") : null); // Make path Unix-like for comparison (e.g. on Windows)
|
||||
final String rootPathFileURI = "file://" + rootPathUnix;
|
||||
final String collapsedRootPathFileURI = rootPathFileURI.replace("//", "/"); // Config string may have been transformed
|
||||
final String rootPathWarFileURI = "war:file://" + rootPathUnix;
|
||||
final String collapsedRootPathWarFileURI = rootPathWarFileURI.replace("//", "/"); // Config string may have been transformed
|
||||
|
||||
if (config != null && (rootPath == null || config.startsWith(rootPath) ||
|
||||
config.startsWith(rootPathFileURI) || config.startsWith(collapsedRootPathFileURI) ||
|
||||
config.startsWith(rootPathWarFileURI) || config.startsWith(collapsedRootPathWarFileURI))) {
|
||||
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;
|
||||
}
|
||||
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
|
||||
*/
|
||||
public void setClassName(String className) {
|
||||
if (className != null && className.trim().length() > 0) {
|
||||
this.className = className;
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @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 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 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;
|
||||
}
|
||||
/**
|
||||
* @param padding the padding to set
|
||||
*/
|
||||
public void setPadding(int padding) {
|
||||
this.padding = padding;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return the classLines
|
||||
*/
|
||||
public List getClassLines() {
|
||||
return classLines;
|
||||
}
|
||||
/**
|
||||
* @return the classLines
|
||||
*/
|
||||
public List<String> getClassLines() {
|
||||
return classLines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the configLines
|
||||
*/
|
||||
public List getConfigLines() {
|
||||
return configLines;
|
||||
}
|
||||
/**
|
||||
* @return the configLines
|
||||
*/
|
||||
public List<String> getConfigLines() {
|
||||
return configLines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the pageLines
|
||||
*/
|
||||
public List getPageLines() {
|
||||
return pageLines;
|
||||
}
|
||||
/**
|
||||
* @return the pageLines
|
||||
*/
|
||||
public List<String> getPageLines() {
|
||||
return pageLines;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the className
|
||||
*/
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
/**
|
||||
* @return the className
|
||||
*/
|
||||
public String getClassName() {
|
||||
return className;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the config
|
||||
*/
|
||||
public String getConfig() {
|
||||
return config;
|
||||
}
|
||||
/**
|
||||
* @return the config
|
||||
*/
|
||||
public String getConfig() {
|
||||
return config;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the page
|
||||
*/
|
||||
public String getPage() {
|
||||
return page;
|
||||
}
|
||||
/**
|
||||
* @return the page
|
||||
*/
|
||||
public String getPage() {
|
||||
return page;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the configLine
|
||||
*/
|
||||
public int getConfigLine() {
|
||||
return configLine;
|
||||
}
|
||||
/**
|
||||
* @return the configLine
|
||||
*/
|
||||
public int getConfigLine() {
|
||||
return configLine;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the padding
|
||||
*/
|
||||
public int getPadding() {
|
||||
return padding;
|
||||
}
|
||||
/**
|
||||
* @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));
|
||||
/**
|
||||
* 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<String> read(InputStream in, int targetLineNumber) {
|
||||
List<String> 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;
|
||||
}
|
||||
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 withServletContext(ServletContext arg0) {
|
||||
this.servletContext = arg0;
|
||||
}
|
||||
public void withServletContext(ServletContext arg0) {
|
||||
this.servletContext = arg0;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
+56
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -22,15 +22,14 @@
|
||||
<Configuration>
|
||||
<Appenders>
|
||||
<Console name="STDOUT" target="SYSTEM_OUT">
|
||||
<PatternLayout pattern="%d %-5p [%t] %C{2} (%F:%L) - %m%n"/>
|
||||
<PatternLayout pattern="[%-5p] %C{2} (%F:%L) - %m%n"/>
|
||||
</Console>
|
||||
</Appenders>
|
||||
<Loggers>
|
||||
<Logger name="com.opensymphony.xwork2" level="info"/>
|
||||
<Logger name="org.apache.struts2" level="info"/>
|
||||
<Logger name="org.springframework" level="info"/>
|
||||
<Root level="info">
|
||||
<AppenderRef ref="STDOUT"/>
|
||||
</Root>
|
||||
<Logger name="org.apache.struts2" level="info"/>
|
||||
<Logger name="com.opensymphony.xwork2" level="info"/>
|
||||
</Loggers>
|
||||
</Configuration>
|
||||
</Configuration>
|
||||
|
||||
+7
-7
@@ -21,31 +21,31 @@
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC
|
||||
"-//Apache Struts//XWork Validator 1.0.2//EN"
|
||||
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
<validators>
|
||||
<field name="description1">
|
||||
<field-validator type="requiredstring">
|
||||
<message>Description1 Is Required !!!</message>
|
||||
</field-validator>
|
||||
</field>
|
||||
|
||||
|
||||
<field name="description2">
|
||||
<field-validator type="requiredstring">
|
||||
<message>Description2 Is Required !!!</message>
|
||||
</field-validator>
|
||||
</field>
|
||||
|
||||
|
||||
<field name="description3">
|
||||
<field-validator type="requiredstring">
|
||||
<message>Description3 Is Required !!!</message>
|
||||
</field-validator>
|
||||
</field>
|
||||
|
||||
|
||||
<field name="description4">
|
||||
<field-validator type="requiredstring">
|
||||
<message>Description4 Is Required !!!</message>
|
||||
</field-validator>
|
||||
</field>
|
||||
</validators>
|
||||
|
||||
</validators>
|
||||
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.dtd">
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.dtd">
|
||||
<validators>
|
||||
<!-- Field-Validator Syntax -->
|
||||
<field name="currentEmployee.empId">
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.dtd">
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.dtd">
|
||||
<validators>
|
||||
<!-- Field-Validator Syntax -->
|
||||
<field name="currentSkill.name">
|
||||
|
||||
+2
-3
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC
|
||||
"-//Apache Struts//XWork Validator 1.0.2//EN"
|
||||
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
<validators>
|
||||
<field name="upload">
|
||||
@@ -35,5 +35,4 @@
|
||||
<message>Caption cannot be empty</message>
|
||||
</field-validator>
|
||||
</field>
|
||||
</validators>
|
||||
|
||||
</validators>
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.dtd">
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.dtd">
|
||||
<validators>
|
||||
<field name="person">
|
||||
<field-validator type="visitor">
|
||||
|
||||
+1
-1
@@ -19,7 +19,7 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.dtd">
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.dtd">
|
||||
<validators>
|
||||
<field name="name">
|
||||
<field-validator type="requiredstring">
|
||||
|
||||
+6
-6
@@ -21,8 +21,8 @@
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC
|
||||
"-//Apache Struts//XWork Validator 1.0.2//EN"
|
||||
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
<validators>
|
||||
<field name="value">
|
||||
<field-validator type="requiredstring">
|
||||
@@ -30,13 +30,13 @@
|
||||
<message>Value must not be empty</message>
|
||||
</field-validator>
|
||||
</field>
|
||||
|
||||
|
||||
|
||||
|
||||
<field name="count">
|
||||
<field-validator type="int">
|
||||
<message>Count must be an integer</message>
|
||||
</field-validator>
|
||||
</field-validator>
|
||||
</field>
|
||||
</validators>
|
||||
</validators>
|
||||
|
||||
|
||||
|
||||
+4
-4
@@ -21,10 +21,10 @@
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC
|
||||
"-//Apache Struts//XWork Validator 1.0//EN"
|
||||
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
<!-- START SNIPPET: fieldValidatorsExample -->
|
||||
|
||||
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
<!-- START SNIPPET: fieldValidatorsExample -->
|
||||
|
||||
<validators>
|
||||
<field name="requiredValidatorField">
|
||||
<field-validator type="required">
|
||||
|
||||
+5
-5
@@ -19,12 +19,12 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC
|
||||
<!DOCTYPE validators PUBLIC
|
||||
"-//Apache Struts//XWork Validator 1.0//EN"
|
||||
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
<!-- START SNIPPET: fieldValidatorsExample -->
|
||||
|
||||
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
<!-- START SNIPPET: fieldValidatorsExample -->
|
||||
|
||||
<validators>
|
||||
<field name="requiredValidatorField">
|
||||
<field-validator type="required">
|
||||
|
||||
+6
-6
@@ -19,13 +19,13 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC
|
||||
<!DOCTYPE validators PUBLIC
|
||||
"-//Apache Struts//XWork Validator 1.0//EN"
|
||||
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
|
||||
<!-- START SNIPPET: nonFieldValidatorsExample -->
|
||||
|
||||
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
|
||||
<!-- START SNIPPET: nonFieldValidatorsExample -->
|
||||
|
||||
<validators>
|
||||
<validator type="expression">
|
||||
<param name="expression"><![CDATA[ ( (someText == someTextRetype) && (someTextRetype == someTextRetypeAgain) ) ]]></param>
|
||||
|
||||
+2
-2
@@ -19,11 +19,11 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
<!-- START SNIPPET: quizValidators -->
|
||||
<!--
|
||||
Add the following DOCTYPE declaration as first line of your XXX-validation.xml file:
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
<!DOCTYPE validators PUBLIC "-//Apache Struts//XWork Validator 1.0.2//EN" "https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
-->
|
||||
<validators>
|
||||
<field name="name">
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC
|
||||
"-//Apache Struts//XWork Validator 1.0//EN"
|
||||
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
<validators>
|
||||
<field name="name">
|
||||
|
||||
+5
-5
@@ -19,17 +19,17 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC
|
||||
<!DOCTYPE validators PUBLIC
|
||||
"-//Apache Struts//XWork Validator 1.0//EN"
|
||||
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
<validators>
|
||||
<field name="name">
|
||||
<field-validator type="requiredstring">
|
||||
<message>Name Required</message>
|
||||
</field-validator>
|
||||
</field>
|
||||
<field name="age">
|
||||
<field name="age">
|
||||
<field-validator type="int">
|
||||
<param name="min">1</param>
|
||||
<param name="max">100</param>
|
||||
@@ -41,6 +41,6 @@
|
||||
<message>Birthday Required</message>
|
||||
</field-validator>
|
||||
</field>
|
||||
</validators>
|
||||
</validators>
|
||||
|
||||
|
||||
|
||||
+3
-3
@@ -19,10 +19,10 @@
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE validators PUBLIC
|
||||
<!DOCTYPE validators PUBLIC
|
||||
"-//Apache Struts//XWork Validator 1.0//EN"
|
||||
"http://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
"https://struts.apache.org/dtds/xwork-validator-1.0.2.dtd">
|
||||
|
||||
<!-- START SNIPPET: visitorValidatorsExample -->
|
||||
|
||||
<validators>
|
||||
|
||||
@@ -21,12 +21,12 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="actionchaining" extends="struts-default" namespace="/actionchaining">
|
||||
<action name="actionChain1" class="org.apache.struts2.showcase.actionchaining.ActionChain1">
|
||||
<result type="chain">actionChain2</result>
|
||||
<result type="chain">actionChain2</result>
|
||||
</action>
|
||||
<action name="actionChain2" class="org.apache.struts2.showcase.actionchaining.ActionChain2">
|
||||
<result type="chain">actionChain3</result>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="async" extends="json-default" namespace="/async">
|
||||
|
||||
@@ -21,15 +21,15 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="conversion" namespace="/conversion" extends="struts-default">
|
||||
|
||||
|
||||
<action name="index">
|
||||
<result>/WEB-INF/conversion/index.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
<!-- Example populating a List inside an Action -->
|
||||
<action name="enterPersonsInfo" method="input"
|
||||
class="org.apache.struts2.showcase.conversion.PersonAction">
|
||||
@@ -49,8 +49,8 @@
|
||||
<action name="showPersonJavaCode">
|
||||
<result type="plainText">/WEB-INF/conversion/Person.java.txt</result>
|
||||
</action>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- Example populating a Set inside an Action -->
|
||||
<action name="enterAddressesInfo" class="org.apache.struts2.showcase.conversion.AddressAction" method="input">
|
||||
<result>/WEB-INF/conversion/enterAddressInfo.jsp</result>
|
||||
@@ -68,9 +68,9 @@
|
||||
<action name="showAddressJavaCode">
|
||||
<result type="plainText">/WEB-INF/conversion/Address.java.txt</result>
|
||||
</action>
|
||||
|
||||
|
||||
<!-- Example populating a List with Tiger 5 Enum -->
|
||||
|
||||
|
||||
<!-- Example populating a List with Tiger 5 Enum -->
|
||||
<action name="enterOperationEnumInfo" class="org.apache.struts2.showcase.conversion.OperationsEnumAction" method="input">
|
||||
<result>/WEB-INF/conversion/enterOperations.jsp</result>
|
||||
</action>
|
||||
@@ -93,6 +93,6 @@
|
||||
<action name="showOperationsEnumActionConversionProperties">
|
||||
<result type="plainText">/WEB-INF/conversion/OperationsEnumActionConversion.txt</result>
|
||||
</action>
|
||||
|
||||
|
||||
</package>
|
||||
</struts>
|
||||
</struts>
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="dispatcher" extends="struts-default" namespace="/dispatcher">
|
||||
|
||||
<action name="dispatch">
|
||||
<result type="dispatcher">
|
||||
/WEB-INF/dispatcher/dispatch-result.jsp
|
||||
</result>
|
||||
</action>
|
||||
|
||||
<action name="forward">
|
||||
<result type="dispatcher">/dispatcher/dispatch.action</result>
|
||||
</action>
|
||||
|
||||
</package>
|
||||
</struts>
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="filedownload" extends="struts-default" namespace="/filedownload">
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="fileupload" extends="struts-default" namespace="/fileupload">
|
||||
|
||||
|
||||
<action name="upload" class="org.apache.struts2.showcase.fileupload.FileUploadAction" method="input">
|
||||
<result>/WEB-INF/fileupload/upload.jsp</result>
|
||||
</action>
|
||||
@@ -34,11 +34,11 @@
|
||||
<result name="input">/WEB-INF/fileupload/upload.jsp</result>
|
||||
<result>/WEB-INF/fileupload/upload-success.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
<action name="multipleUploadUsingList">
|
||||
<result>/WEB-INF/fileupload/multipleUploadUsingList.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
<action name="doMultipleUploadUsingList" class="org.apache.struts2.showcase.fileupload.MultipleFileUploadUsingListAction" method="upload">
|
||||
<result name="input">/WEB-INF/fileupload/multipleUploadUsingList.jsp</result>
|
||||
<result>/WEB-INF/fileupload/multiple-success.jsp</result>
|
||||
|
||||
@@ -21,16 +21,16 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="freemarker" namespace="/freemarker" extends="struts-default">
|
||||
<action name="customFreemarkerManagerDemo">
|
||||
<result type="freemarker">/WEB-INF/freemarker/customFreemarkerManagerUsage.ftl</result>
|
||||
</action>
|
||||
|
||||
|
||||
<action name="standardTags" class="org.apache.struts2.showcase.freemarker.StandardTagsAction">
|
||||
<result type="freemarker">/WEB-INF/freemarker/standardTags.ftl</result>
|
||||
</action>
|
||||
</package>
|
||||
</struts>
|
||||
</struts>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="hangman" extends="struts-default" namespace="/hangman">
|
||||
@@ -41,9 +41,9 @@
|
||||
<result type="freemarker">/WEB-INF/hangman/hangmanNonAjax.ftl</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<package name="hangman-ajax" extends="struts-default" namespace="/hangman/ajax">
|
||||
<action name="blank">
|
||||
<result type="freemarker">/WEB-INF/hangman/blank.ftl</result>
|
||||
@@ -61,4 +61,4 @@
|
||||
<result type="freemarker">/WEB-INF/hangman/updateGuessLeft.ftl</result>
|
||||
</action>
|
||||
</package>
|
||||
</struts>
|
||||
</struts>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="interactive" namespace="/interactive" extends="struts-default">
|
||||
@@ -38,4 +38,4 @@
|
||||
</action>
|
||||
<action name="example" class="org.apache.struts2.showcase.action.ExampleAction" />
|
||||
</package>
|
||||
</struts>
|
||||
</struts>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="modelDriven" extends="struts-default" namespace="/modelDriven">
|
||||
@@ -29,11 +29,10 @@
|
||||
<action name="modelDriven" class="org.apache.struts2.showcase.modelDriven.ModelDrivenAction" method="input">
|
||||
<result>/WEB-INF/modelDriven/modelDriven.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
<!-- Display the result page whose content is populated using the Model-Driven technique -->
|
||||
<action name="modelDrivenResult" class="org.apache.struts2.showcase.modelDriven.ModelDrivenAction">
|
||||
<result>/WEB-INF/modelDriven/modelDrivenResult.jsp</result>
|
||||
</action>
|
||||
</package>
|
||||
</struts>
|
||||
|
||||
</struts>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<!-- START SNIPPET: xworkSample -->
|
||||
|
||||
|
||||
@@ -21,14 +21,14 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
|
||||
|
||||
<!-- ================================== -->
|
||||
<!-- === Package for ActionTag Demo === -->
|
||||
<!-- ================================== -->
|
||||
|
||||
|
||||
<package name="actionTag" extends="struts-default" namespace="/tags/non-ui/actionTag">
|
||||
<action name="showActionTagDemo" class="org.apache.struts2.showcase.tag.nonui.actiontag.ActionTagDemo" method="show">
|
||||
<result>/WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp</result>
|
||||
@@ -46,11 +46,11 @@
|
||||
<result type="plainText">/WEB-INF/tags/non-ui/actionTag/showActionTagDemo.jsp</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
|
||||
<!-- ==================================== -->
|
||||
<!-- === Package for IteratorGeneratorTag Demo === -->
|
||||
<!-- ==================================== -->
|
||||
|
||||
|
||||
<package name="iteratorGeneratorTag" extends="struts-default" namespace="/tags/non-ui/iteratorGeneratorTag">
|
||||
<action name="showGeneratorTagDemo" class="org.apache.struts2.showcase.tag.nonui.iteratortag.IteratorGeneratorTagDemo" method="input">
|
||||
<result>/WEB-INF/tags/non-ui/iteratorTag/showIteratorGeneratorTagDemo.jsp</result>
|
||||
@@ -60,8 +60,8 @@
|
||||
<result>/WEB-INF/tags/non-ui/iteratorTag/iteratorGeneratorTagDemoResult.jsp</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ===================================== -->
|
||||
<!-- === Package for AppendIteratorTag Demo === -->
|
||||
<!-- ========================================== -->
|
||||
@@ -74,8 +74,8 @@
|
||||
<result>/WEB-INF/tags/non-ui/iteratorTag/appendIteratorTagDemoResult.jsp</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ====================================== -->
|
||||
<!-- === Package for MergeIteratorTag Demo === -->
|
||||
<!-- ========================================= -->
|
||||
@@ -88,7 +88,7 @@
|
||||
<result>/WEB-INF/tags/non-ui/iteratorTag/mergeIteratorTagDemoResult.jsp</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
|
||||
<!-- ============================================= -->
|
||||
<!-- === Package for SubsetIteratorTag Demo === -->
|
||||
<!-- =========================================== -->
|
||||
@@ -101,14 +101,14 @@
|
||||
<result>/WEB-INF/tags/non-ui/iteratorTag/subsetIteratorTagDemoResult.jsp</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
|
||||
<!-- ========================================= -->
|
||||
<!-- === Package for Action Prefix Example === -->
|
||||
<!-- ========================================= -->
|
||||
<package name="actionPrefix" extends="struts-default" namespace="/tags/non-ui/actionPrefix">
|
||||
<action name="actionPrefixExampleUsingFreemarker">
|
||||
<result type="freemarker">/WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl</result>
|
||||
</action>
|
||||
</action>
|
||||
<action name="submit" class="org.apache.struts2.showcase.tag.nonui.actionPrefix.SubmitAction">
|
||||
<result type="freemarker">/WEB-INF/tags/non-ui/actionPrefix/normalSubmit.ftl</result>
|
||||
</action>
|
||||
@@ -131,7 +131,7 @@
|
||||
<result type="plainText">/WEB-INF/tags/non-ui/actionPrefix/actionPrefixExample.ftl</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
|
||||
<!-- ========================================== -->
|
||||
<!-- === Package for If Tag Test / Examples === -->
|
||||
<!-- ========================================== -->
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="ui-tags" extends="velocity-default" namespace="/tags/ui">
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<include file="struts-tags-ui.xml"/>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="tiles" extends="tiles-default" namespace="/tiles">
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
<struts>
|
||||
<package name="token" extends="struts-default" namespace="/token">
|
||||
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
|
||||
<constant name="struts.beanValidation.providerClass" value="org.hibernate.validator.HibernateValidator"/>
|
||||
@@ -74,7 +74,7 @@
|
||||
<action name="ajaxFormSubmitSuccess" class="org.apache.struts2.showcase.validation.AjaxFormSubmitSuccessAction">
|
||||
<result>/WEB-INF/validation/ajaxFormSubmitSuccess.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
</package>
|
||||
|
||||
|
||||
@@ -83,46 +83,46 @@
|
||||
<action name="list">
|
||||
<result>index.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ======================== -->
|
||||
<!-- === Field Validators === -->
|
||||
<!-- ======================== -->
|
||||
|
||||
|
||||
<action name="showFieldValidatorsExamples" class="org.apache.struts2.showcase.validation.FieldValidatorsExampleAction" method="input">
|
||||
<result name="input" type="dispatcher">/WEB-INF/validation/fieldValidatorsExample.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
<action name="submitFieldValidatorsExamples" class="org.apache.struts2.showcase.validation.FieldValidatorsExampleAction" method="submit">
|
||||
<result name="input" type="dispatcher">/WEB-INF/validation/fieldValidatorsExample.jsp</result>
|
||||
<result type="dispatcher">/WEB-INF/validation/successFieldValidatorsExample.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ============================ -->
|
||||
<!-- === Non Field Validators === -->
|
||||
<!-- ============================ -->
|
||||
|
||||
|
||||
<action name="showNonFieldValidatorsExamples" class="org.apache.struts2.showcase.validation.NonFieldValidatorsExampleAction" method="input">
|
||||
<result name="input">/WEB-INF/validation/nonFieldValidatorsExample.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
<action name="submitNonFieldValidatorsExamples" class="org.apache.struts2.showcase.validation.NonFieldValidatorsExampleAction" method="submit">
|
||||
<result name="input">/WEB-INF/validation/nonFieldValidatorsExample.jsp</result>
|
||||
<result>/WEB-INF/validation/successNonFieldValidatorsExample.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<!-- ========================== -->
|
||||
<!-- === Visitor Validators === -->
|
||||
<!-- ========================== -->
|
||||
|
||||
|
||||
<action name="showVisitorValidatorsExamples" class="org.apache.struts2.showcase.validation.VisitorValidatorsExampleAction" method="input">
|
||||
<result name="input">/WEB-INF/validation/visitorValidatorsExample.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
<action name="submitVisitorValidatorsExamples" class="org.apache.struts2.showcase.validation.VisitorValidatorsExampleAction" method="submit">
|
||||
<result name="input">/WEB-INF/validation/visitorValidatorsExample.jsp</result>
|
||||
<result>/WEB-INF/validation/successVisitorValidatorsExample.jsp</result>
|
||||
@@ -146,7 +146,7 @@
|
||||
<!-- =========================================== -->
|
||||
<!-- === Store Error Messages Across Request === -->
|
||||
<!-- =========================================== -->
|
||||
|
||||
|
||||
<action name="submitApplication" class="org.apache.struts2.showcase.validation.SubmitApplication" method="submitApplication">
|
||||
<interceptor-ref name="store">
|
||||
<param name="operationMode">STORE</param>
|
||||
@@ -173,7 +173,7 @@
|
||||
<action name="cancelApplication" class="org.apache.struts2.showcase.validation.SubmitApplication" method="cancelApplication">
|
||||
<result>/WEB-INF/validation/storeErrorsAcrossRequestCancel.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
</package>
|
||||
</struts>
|
||||
|
||||
|
||||
|
||||
@@ -21,10 +21,17 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
|
||||
<bean type="org.apache.struts2.interceptor.exec.ExecutorProvider" class="org.apache.struts2.showcase.wait.ThreadPoolExecutorProvider"/>
|
||||
|
||||
<package name="wait" extends="struts-default" namespace="/wait">
|
||||
<default-action-ref name="index"/>
|
||||
<action name="index">
|
||||
<result>/WEB-INF/wait/index.jsp</result>
|
||||
</action>
|
||||
|
||||
<action name="example1">
|
||||
<result>/WEB-INF/wait/example1.jsp</result>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<package name="xslt" extends="struts-default" namespace="/xslt">
|
||||
@@ -36,7 +36,7 @@
|
||||
<param name="exposedValue">info.classpath</param>
|
||||
</result>
|
||||
</action>
|
||||
|
||||
|
||||
<action name="jvmInfoRaw" class="org.apache.struts2.showcase.xslt.JVMAction">
|
||||
<result type="xslt">
|
||||
<param name="exposedValue">info</param>
|
||||
|
||||
@@ -21,7 +21,7 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<!-- START SNIPPET: xworkSample -->
|
||||
<struts>
|
||||
@@ -78,6 +78,8 @@
|
||||
|
||||
<include file="struts-async.xml" />
|
||||
|
||||
<include file="struts-dispatcher.xml" />
|
||||
|
||||
<package name="default" extends="struts-default">
|
||||
<interceptors>
|
||||
<interceptor-stack name="crudStack">
|
||||
|
||||
@@ -45,66 +45,46 @@
|
||||
</bean>
|
||||
|
||||
<bean id="chatLoginAction" class="org.apache.struts2.showcase.chat.ChatLoginAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="chatLogoutAction" class="org.apache.struts2.showcase.chat.ChatLogoutAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="usersAvailableAction" class="org.apache.struts2.showcase.chat.UsersAvailableAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="roomsAvailableAction" class="org.apache.struts2.showcase.chat.RoomsAvailableAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="crudRoomAction" class="org.apache.struts2.showcase.chat.CrudRoomAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="enterRoomAction" class="org.apache.struts2.showcase.chat.EnterRoomAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="messagesAvailableInRoomAction" class="org.apache.struts2.showcase.chat.MessagesAvailableInRoomAction"
|
||||
scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="sendMessageToRoomAction" class="org.apache.struts2.showcase.chat.SendMessageToRoomAction"
|
||||
scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="usersAvailableInRoomAction" class="org.apache.struts2.showcase.chat.UsersAvailableInRoomAction"
|
||||
scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="exitRoomAction" class="org.apache.struts2.showcase.chat.ExitRoomAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="chatService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="chatService"/>
|
||||
</bean>
|
||||
|
||||
|
||||
@@ -129,9 +109,7 @@
|
||||
</bean>
|
||||
|
||||
<bean id="startHangmanAction" class="org.apache.struts2.showcase.hangman.StartHangmanAction" scope="prototype">
|
||||
<constructor-arg index="0">
|
||||
<ref local="hangmanService"/>
|
||||
</constructor-arg>
|
||||
<constructor-arg index="0" ref="hangmanService"/>
|
||||
</bean>
|
||||
|
||||
<bean id="guessCharacterAction" class="org.apache.struts2.showcase.hangman.GuessCharacterAction" scope="prototype"/>
|
||||
|
||||
@@ -64,14 +64,14 @@
|
||||
<title><decorator:title default="Struts2 Showcase"/></title>
|
||||
|
||||
<s:url var="bootstrapCss" value='/styles/bootstrap.css' encode='false' includeParams='none'/>
|
||||
<s:link href="%{bootstrapCss}" rel="stylesheet" type="text/css" media="all"></s:link>
|
||||
<s:link href="%{bootstrapCss}" rel="stylesheet" type="text/css" media="all"/>
|
||||
<s:url var="mainCss" value='/styles/main.css' encode='false' includeParams='none'/>
|
||||
<s:link href="%{mainCss}" rel="stylesheet" type="text/css" media="all"></s:link>
|
||||
<s:link href="%{mainCss}" rel="stylesheet" type="text/css" media="all"/>
|
||||
|
||||
<s:url var="jqueryJs" value='/js/jquery-2.1.4.min.js' encode='false' includeParams='none'/>
|
||||
<s:script src="%{jqueryJs}"></s:script>
|
||||
<s:script src="%{jqueryJs}"/>
|
||||
<s:url var="bootstrapJs" value='/js/bootstrap.min.js' encode='false' includeParams='none'/>
|
||||
<s:script src="%{bootstrapJs}"></s:script>
|
||||
<s:script src="%{bootstrapJs}"/>
|
||||
<s:script type="text/javascript">
|
||||
$(function () {
|
||||
var alerts = $('ul.alert').wrap('<div />');
|
||||
@@ -82,19 +82,22 @@
|
||||
|
||||
<!-- Prettify -->
|
||||
<s:url var="prettifyCss" value='/styles/prettify.css' encode='false' includeParams='none'/>
|
||||
<s:link href="%{prettifyCss}" rel="stylesheet"></s:link>
|
||||
<s:link href="%{prettifyCss}" rel="stylesheet"/>
|
||||
<s:url var="prettifyJs" value='/js/prettify.js' encode='false' includeParams='none'/>
|
||||
<s:script src="%{prettifyJs}"></s:script>
|
||||
<s:script src="%{prettifyJs}"/>
|
||||
|
||||
<!-- Le HTML5 shim, for IE6-8 support of HTML5 elements -->
|
||||
<!--[if lt IE 9]>
|
||||
<s:script src="http://html5shim.googlecode.com/svn/trunk/html5.js"></s:script>
|
||||
<s:script src="http://html5shim.googlecode.com/svn/trunk/html5.js"/>
|
||||
<![endif]-->
|
||||
|
||||
<s:script>
|
||||
jQuery(document).ready(function() { prettyPrint(); } );
|
||||
</s:script>
|
||||
<decorator:head/>
|
||||
</head>
|
||||
|
||||
<body id="page-home" onload="prettyPrint();">
|
||||
<body id="page-home">
|
||||
|
||||
<nav class="navbar navbar-default navbar-fixed-top">
|
||||
<div class="container-fluid">
|
||||
@@ -239,11 +242,13 @@
|
||||
</li>
|
||||
<li><s:a value="/person/index.html">Person Manager</s:a></li>
|
||||
<li><s:a value="/skill/index.html">CRUD</s:a></li>
|
||||
<li><s:a value="/wait/index.html">Execute & Wait</s:a></li>
|
||||
<li><s:a value="/wait/index">Execute & Wait</s:a></li>
|
||||
<li><s:a value="/token/index.html">Token</s:a></li>
|
||||
<li><s:url var="url" namespace="/modelDriven" action="modelDriven"/><s:a
|
||||
href="%{url}">Model Driven</s:a></li>
|
||||
<li><s:a value="/async/index.html">Async</s:a></li>
|
||||
<li><s:a value="/dispatcher/dispatch.action">Dispatcher result - dispatch</s:a></li>
|
||||
<li><s:a value="/dispatcher/forward.action">Dispatcher result - forward</s:a></li>
|
||||
</ul>
|
||||
</li>
|
||||
<li class="dropdown">
|
||||
|
||||
@@ -0,0 +1,42 @@
|
||||
<!--
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<%@ page contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" %>
|
||||
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Struts2 Showcase - Dispatcher result Example</title>
|
||||
<s:head theme="xhtml"/>
|
||||
</head>
|
||||
<body>
|
||||
|
||||
<div class="page-header">
|
||||
<h1>Dispatcher Result Example</h1>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div id="dispatcher-result" class="col-md-12">
|
||||
This page is a result of "dispatching" to it from an action
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,19 +1,19 @@
|
||||
<!--
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
@@ -26,49 +26,46 @@
|
||||
<body>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>View Sources</h1>
|
||||
<div class="row">
|
||||
<div class="col-md-12">
|
||||
<h1>View Sources</h1>
|
||||
|
||||
<ul class="nav nav-tabs" id="codeTab">
|
||||
<li class="active"><a href="#page">Page</a></li>
|
||||
<li><a href="#config">Configuration</a></li>
|
||||
<li><a href="#java">Java Action</a></li>
|
||||
</ul>
|
||||
<ul class="nav nav-tabs" id="codeTab">
|
||||
<li class="active"><a href="#page">Page</a></li>
|
||||
<li><a href="#config">Configuration</a></li>
|
||||
<li><a href="#java">Java Action</a></li>
|
||||
</ul>
|
||||
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="page">
|
||||
<h3><s:property default="Unknown page" value="page"/></h3>
|
||||
<pre class="prettyprint lang-html linenums">
|
||||
<s:iterator value="pageLines" status="row">
|
||||
<div class="tab-content">
|
||||
<div class="tab-pane active" id="page">
|
||||
<h3><s:property default="Unknown page" value="page"/></h3>
|
||||
<pre class="prettyprint lang-html linenums"><s:iterator value="pageLines" status="row">
|
||||
<s:property/></s:iterator>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="tab-pane" id="config">
|
||||
<h3><s:property default="Unknown configuration" value="config"/></h3>
|
||||
<pre class="prettyprint lang-xml linenums">
|
||||
<s:iterator value="configLines" status="row">
|
||||
</pre>
|
||||
</div>
|
||||
<div class="tab-pane" id="config">
|
||||
<h3><s:property default="Unknown configuration" value="config"/></h3>
|
||||
<pre class="prettyprint lang-xml linenums"><s:iterator value="configLines" status="row">
|
||||
<s:property/></s:iterator>
|
||||
</pre>
|
||||
</div>
|
||||
<div class="tab-pane" id="java">
|
||||
<h3><s:property default="Unknown or unavailable Action class" value="className"/></h3>
|
||||
<pre class="prettyprint lang-java linenums">
|
||||
<s:iterator value="classLines" status="row">
|
||||
</pre>
|
||||
</div>
|
||||
<div class="tab-pane" id="java">
|
||||
<h3><s:property default="Unknown or unavailable Action class" value="className"/></h3>
|
||||
<pre class="prettyprint lang-java linenums"><s:iterator value="classLines" status="row">
|
||||
<s:property/></s:iterator>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<s:script>
|
||||
$('#codeTab a').click(function (e) {
|
||||
e.preventDefault();
|
||||
$(this).tab('show');
|
||||
})
|
||||
$('#codeTab a').click(function (e) {
|
||||
e.preventDefault();
|
||||
$(this).tab('show');
|
||||
})
|
||||
</s:script>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
<!--
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
@@ -21,25 +21,26 @@
|
||||
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Struts2 Showcase - Execute and Wait Examples - Complete</title>
|
||||
<title>Struts2 Showcase - Execute and Wait Examples - Complete</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page-header">
|
||||
<h1>The process is complete</h1>
|
||||
<h1>The process is complete</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
|
||||
<b>We have processed your request.</b>
|
||||
<p/>
|
||||
Click here to <s:url var="back" value="/wait/index.html"/><s:a href="%{back}" cssClass="btn btn-link">return</s:a>.
|
||||
<div class="panel">We have processed your request.</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
<s:url var="back" value="/wait/index"/>
|
||||
Click here to <s:a href="%{back}" cssClass="btn btn-primary">return</s:a>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -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.
|
||||
*/
|
||||
-->
|
||||
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Struts2 Showcase - Execute and Wait Examples</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page-header">
|
||||
<h1>Execute and Wait Examples</h1>
|
||||
</div>
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
|
||||
<p>
|
||||
These examples illustrate Struts build in support for execute and wait.
|
||||
<p/>
|
||||
<p>
|
||||
When you have a process that takes a long time your users can be impatient and starts to submit/click
|
||||
again.
|
||||
<br/> A good solution is to show the user a progress page (wait page) while the process takes it time.
|
||||
<p/>
|
||||
|
||||
<br/>
|
||||
<br/><a href='<s:url value="example1"/>'>Example 1 (no delay)</a>
|
||||
<br/><a href='<s:url value="example2"/>'>Example 2 (with delay)</a>
|
||||
<br/><a href='<s:url value="example3"/>'>Example 3 (with longer check delay)</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,19 +1,19 @@
|
||||
<!--
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
@@ -21,53 +21,33 @@
|
||||
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Struts2 Showcase - Execute and Wait Examples - Wait</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page-header">
|
||||
<h1>Execute and Wait Examples - Wait</h1>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
|
||||
<p class="well">
|
||||
We are processing your request. Please wait.
|
||||
</p>
|
||||
|
||||
<div class="progress progress-striped active">
|
||||
<div class="bar" style="width: 50%;"></div>
|
||||
</div>
|
||||
|
||||
<p/>
|
||||
You can click this link to <a href="<s:url includeParams="all"/>">refresh</a>.
|
||||
|
||||
<b>We have processed your request.</b>
|
||||
<p/>
|
||||
Click here to <s:url var="back" value="/wait/index.html"/><s:a href="%{back}" cssClass="btn btn-link">return</s:a>.
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
<%@ taglib prefix="s" uri="/struts-tags" %>
|
||||
<html>
|
||||
<head>
|
||||
<title>Struts2 Showcase - Execute and Wait Examples - Wait</title>
|
||||
<meta http-equiv="refresh" content="5;url=<s:url includeParams="all"/>"/>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<p style="border: 1px solid silver; padding: 5px; background: #ffd; text-align: center;">
|
||||
We are processing your request. Please wait.
|
||||
</p>
|
||||
<div class="page-header">
|
||||
<h1>Execute and Wait Examples - Wait</h1>
|
||||
</div>
|
||||
|
||||
<p/>
|
||||
You can click this link to <a href="<s:url includeParams="all"/>">refresh</a>.
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
|
||||
<p class="well">
|
||||
We are processing your request. Please wait.
|
||||
</p>
|
||||
|
||||
<div class="progress progress-striped active">
|
||||
<div class="bar progress-bar progress-bar-success" style="width: 50%;"></div>
|
||||
</div>
|
||||
|
||||
<div class="panel">
|
||||
You can click this link to <a href="<s:url includeParams="all"/>">refresh</a>.
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
@@ -16,20 +17,16 @@
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<web-app id="starter" version="2.5" xmlns="http://java.sun.com/xml/ns/javaee"
|
||||
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd">
|
||||
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
|
||||
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
|
||||
version="3.1">
|
||||
|
||||
<display-name>Struts Showcase Application</display-name>
|
||||
|
||||
<context-param>
|
||||
<param-name>org.apache.tiles.definition.DefinitionsFactory.DEFINITIONS_CONFIG</param-name>
|
||||
<param-value>
|
||||
/WEB-INF/tiles.xml
|
||||
</param-value>
|
||||
</context-param>
|
||||
|
||||
<filter>
|
||||
<filter-name>async</filter-name>
|
||||
<filter-class>org.apache.struts2.showcase.async.AsyncFilter</filter-class>
|
||||
@@ -39,18 +36,20 @@
|
||||
<filter>
|
||||
<filter-name>struts-prepare</filter-name>
|
||||
<filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareFilter</filter-class>
|
||||
<async-supported>true</async-supported>
|
||||
</filter>
|
||||
|
||||
<filter>
|
||||
<filter-name>struts-execute</filter-name>
|
||||
<filter-class>org.apache.struts2.dispatcher.filter.StrutsExecuteFilter</filter-class>
|
||||
<async-supported>true</async-supported>
|
||||
</filter>
|
||||
|
||||
|
||||
<filter>
|
||||
<filter-name>sitemesh</filter-name>
|
||||
<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
|
||||
</filter>
|
||||
<filter>
|
||||
<filter-name>sitemesh</filter-name>
|
||||
<filter-class>com.opensymphony.sitemesh.webapp.SiteMeshFilter</filter-class>
|
||||
<async-supported>true</async-supported>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>async</filter-name>
|
||||
@@ -60,16 +59,22 @@
|
||||
<filter-mapping>
|
||||
<filter-name>struts-prepare</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<dispatcher>FORWARD</dispatcher>
|
||||
<dispatcher>REQUEST</dispatcher>
|
||||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>sitemesh</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<dispatcher>FORWARD</dispatcher>
|
||||
<dispatcher>REQUEST</dispatcher>
|
||||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>struts-execute</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
<dispatcher>FORWARD</dispatcher>
|
||||
<dispatcher>REQUEST</dispatcher>
|
||||
</filter-mapping>
|
||||
|
||||
<listener>
|
||||
@@ -81,18 +86,18 @@
|
||||
org.apache.struts2.tiles.StrutsTilesListener
|
||||
</listener-class>
|
||||
</listener>
|
||||
|
||||
|
||||
<!-- Chat Example in Showcase -->
|
||||
<listener>
|
||||
<listener-class>
|
||||
org.apache.struts2.showcase.chat.ChatSessionListener
|
||||
</listener-class>
|
||||
<listener-class>
|
||||
org.apache.struts2.showcase.chat.ChatSessionListener
|
||||
</listener-class>
|
||||
</listener>
|
||||
|
||||
<listener>
|
||||
<listener-class>org.apache.struts2.dispatcher.listener.StrutsListener</listener-class>
|
||||
</listener>
|
||||
|
||||
|
||||
<!-- SNIPPET START: dwr -->
|
||||
|
||||
<servlet>
|
||||
@@ -103,13 +108,20 @@
|
||||
<param-value>true</param-value>
|
||||
</init-param>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>JspSupportServlet</servlet-name>
|
||||
<servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
<servlet>
|
||||
<servlet-name>JspSupportServlet</servlet-name>
|
||||
<servlet-class>org.apache.struts2.views.JspSupportServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<!-- Sitemesh Freemarker and Velocity Decorator Servlets. Shares configuration with Struts.-->
|
||||
<servlet>
|
||||
<servlet-name>strutsServlet</servlet-name>
|
||||
<servlet-class>org.apache.struts2.dispatcher.servlet.StrutsServlet</servlet-class>
|
||||
<load-on-startup>2</load-on-startup>
|
||||
<async-supported>true</async-supported>
|
||||
</servlet>
|
||||
|
||||
<!-- Sitemesh Freemarker and Velocity Decorator Servlets. Shares configuration with Struts.-->
|
||||
<servlet>
|
||||
<servlet-name>sitemesh-freemarker</servlet-name>
|
||||
<servlet-class>org.apache.struts2.sitemesh.FreemarkerDecoratorServlet</servlet-class>
|
||||
@@ -117,7 +129,7 @@
|
||||
<param-name>default_encoding</param-name>
|
||||
<param-value>UTF-8</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
<load-on-startup>3</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
@@ -127,14 +139,7 @@
|
||||
<param-name>default_encoding</param-name>
|
||||
<param-value>UTF-8</param-value>
|
||||
</init-param>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet>
|
||||
<servlet-name>strutsServlet</servlet-name>
|
||||
<servlet-class>org.apache.struts2.dispatcher.servlet.StrutsServlet</servlet-class>
|
||||
<load-on-startup>1</load-on-startup>
|
||||
<async-supported>true</async-supported>
|
||||
<load-on-startup>4</load-on-startup>
|
||||
</servlet>
|
||||
|
||||
<servlet-mapping>
|
||||
|
||||
@@ -1,53 +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.
|
||||
*/
|
||||
-->
|
||||
<html>
|
||||
<head>
|
||||
<title>Struts2 Showcase - Execute and Wait Examples</title>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<div class="page-header">
|
||||
<h1>Execute and Wait Examples</h1>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="container-fluid">
|
||||
<div class="row">
|
||||
<div class="col-md-12" style="text-align: center;">
|
||||
|
||||
<p>
|
||||
These examples illustrate Struts build in support for execute and wait.
|
||||
<p/>
|
||||
<p>
|
||||
When you have a process that takes a long time your users can be impatient and starts to submit/click again.
|
||||
<br/> A good solution is to show the user a progress page (wait page) while the process takes it time.
|
||||
<p/>
|
||||
|
||||
<br/>
|
||||
<br/><a href="example1.action">Example 1 (no delay)</a>
|
||||
<br/><a href="example2.action">Example 2 (with delay)</a>
|
||||
<br/><a href="example3.action">Example 3 (with longer check delay)</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
</html>
|
||||
@@ -32,7 +32,7 @@ public class ActionChainingTest {
|
||||
try (final WebClient webClient = new WebClient()) {
|
||||
final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/actionchaining/actionChain1!input");
|
||||
|
||||
final String pageAsText = page.asText();
|
||||
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"));
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@ public class ActionTagExampleTest {
|
||||
try (final WebClient webClient = new WebClient()) {
|
||||
final HtmlPage page = webClient.getPage(ParameterUtils.getBaseUrl() + "/tags/ui/actionTagExample!input.action");
|
||||
|
||||
final String pageAsText = page.asText();
|
||||
final String pageAsText = page.asNormalizedText();
|
||||
Assert.assertTrue(pageAsText.contains("This text is from the called class"));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -46,7 +46,7 @@ public class AsyncTest {
|
||||
|
||||
final DomElement msgs = page2.getElementById("msgs");
|
||||
|
||||
Assert.assertEquals("hello", msgs.asText());
|
||||
Assert.assertEquals("hello", msgs.asNormalizedText());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -44,7 +44,7 @@ public class CRUDTest {
|
||||
|
||||
final HtmlSubmitInput button = form.getInputByValue("Save");
|
||||
final HtmlPage page2 = button.click();
|
||||
final String page2Text = page2.asText();
|
||||
final String page2Text = page2.asNormalizedText();
|
||||
|
||||
Assert.assertTrue(page2Text.contains("somename1"));
|
||||
Assert.assertTrue(page2Text.contains("somedescription1"));
|
||||
|
||||
+1
-1
@@ -33,7 +33,7 @@ public class ComponentTagExampleTest {
|
||||
final HtmlPage page = webClient
|
||||
.getPage(ParameterUtils.getBaseUrl() + "/tags/ui/componentTagExample.action");
|
||||
|
||||
final String pageAsText = page.asText();
|
||||
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"));
|
||||
|
||||
@@ -46,7 +46,7 @@ public class ConversionTest {
|
||||
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
final HtmlPage page2 = button.click();
|
||||
final String page2Text = page2.asText();
|
||||
final String page2Text = page2.asNormalizedText();
|
||||
|
||||
Assert.assertTrue(page2Text.contains("SET 0 Name: name0"));
|
||||
Assert.assertTrue(page2Text.contains("SET 0 Age: 0"));
|
||||
@@ -71,7 +71,7 @@ public class ConversionTest {
|
||||
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
final HtmlPage page2 = button.click();
|
||||
final String page2Text = page2.asText();
|
||||
final String page2Text = page2.asNormalizedText();
|
||||
|
||||
Assert.assertTrue(page2Text.contains("id0 -> address0"));
|
||||
Assert.assertTrue(page2Text.contains("id1 -> address1"));
|
||||
@@ -92,7 +92,7 @@ public class ConversionTest {
|
||||
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
final HtmlPage page2 = button.click();
|
||||
final String page2Text = page2.asText();
|
||||
final String page2Text = page2.asNormalizedText();
|
||||
|
||||
Assert.assertTrue(page2Text.contains("ADD"));
|
||||
Assert.assertTrue(page2Text.contains("MINUS"));
|
||||
|
||||
@@ -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 it.org.apache.struts2.showcase;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.WebClient;
|
||||
import com.gargoylesoftware.htmlunit.html.DomElement;
|
||||
import com.gargoylesoftware.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()) {
|
||||
webClient.getOptions().setThrowExceptionOnFailingStatusCode(false);
|
||||
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());
|
||||
// support for forwarding to another action is broken on StrutsPrepareFilter/StrutsExecuteFilter
|
||||
// it only works in StrutsPrepareAndExecuteFilter
|
||||
// this will be fixed in Struts 6.1.x
|
||||
|
||||
Assert.assertEquals(404, page.getWebResponse().getStatusCode());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -43,12 +43,12 @@ public class ExecAndWaitTest {
|
||||
final HtmlSubmitInput button = form.getInputByValue("submit");
|
||||
final HtmlPage page2 = button.click();
|
||||
|
||||
Assert.assertTrue(page2.asText().contains("We are processing your request. Please wait."));
|
||||
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.asText().contains("We are processing your request. Please wait."));
|
||||
Assert.assertTrue(page3.asNormalizedText().contains("We are processing your request. Please wait."));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,6 +43,7 @@ public class FileDownloadTest {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZip() throws Exception {
|
||||
try (final WebClient webClient = new WebClient()) {
|
||||
final Page page = webClient.getPage(ParameterUtils.getBaseUrl() + "/filedownload/download2.action");
|
||||
|
||||
+2
-2
@@ -36,11 +36,11 @@ public class FreeMarkerManagerTest {
|
||||
|
||||
final DomElement date = page.getElementById("todaysDate");
|
||||
Assert.assertNotNull(date);
|
||||
Assert.assertTrue(date.asText().length() > 0);
|
||||
Assert.assertTrue(date.asNormalizedText().length() > 0);
|
||||
|
||||
final DomElement time = page.getElementById("timeNow");
|
||||
Assert.assertNotNull(time);
|
||||
Assert.assertTrue(time.asText().length() > 0);
|
||||
Assert.assertTrue(time.asNormalizedText().length() > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -33,26 +33,23 @@ public class StaticContentTest {
|
||||
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 testInvalidRersources2() 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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*public void testInvalidRersources3() throws IOException {
|
||||
try {
|
||||
beginAt("/static/..%252f..%252f..%252fWEB-INF/classes/org/apache/struts2/showcase/action/EmployeeAction.class/");
|
||||
fail("Previous request should have failed");
|
||||
} catch (TestingEngineResponseException ex) {
|
||||
// ok
|
||||
}
|
||||
}*/
|
||||
}
|
||||
|
||||
@@ -65,11 +65,11 @@ public class UITagExampleTest {
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
final HtmlPage page2 = button.click();
|
||||
|
||||
Assert.assertEquals("name", page2.getElementById("name").asText());
|
||||
Assert.assertEquals("bio", page2.getElementById("bio").asText());
|
||||
Assert.assertEquals("Red", page2.getElementById("favouriteColor").asText());
|
||||
Assert.assertEquals("[Patrick, Jason]", page2.getElementById("friends").asText());
|
||||
Assert.assertEquals("true", page2.getElementById("legalAge").asText());
|
||||
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());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public class ValidationTest {
|
||||
|
||||
final HtmlSubmitInput button = form.getInputByValue("Submit");
|
||||
final HtmlPage page2 = button.click();
|
||||
final String page2Text = page2.asText();
|
||||
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\""));
|
||||
|
||||
@@ -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.
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<version>6.1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-assembly</artifactId>
|
||||
|
||||
@@ -36,6 +36,7 @@
|
||||
<include>org.apache.struts:struts2-core</include>
|
||||
<include>org.freemarker:freemarker</include>
|
||||
<include>org.apache.commons:commons-lang3</include>
|
||||
<include>org.apache.commons:commons-text</include>
|
||||
<include>org.apache.logging.log4j:log4j-api</include>
|
||||
<include>ognl:ognl</include>
|
||||
<include>commons-fileupload:commons-fileupload</include>
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
# Struts 2 BOM
|
||||
This is a Bill-Of-Materials to be used with Maven based project. It allows to import all the Struts 2
|
||||
dependencies at once and used them in your project where needed.
|
||||
|
||||
## Installation
|
||||
You must add a proper import statement into your `pom.xml` as presented below:
|
||||
|
||||
```xml
|
||||
<dependencyManagement>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-bom</artifactId>
|
||||
<version>${struts2.version}</version>
|
||||
<type>pom</type>
|
||||
<scope>import</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
```
|
||||
+13
-3
@@ -29,7 +29,7 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-bom</artifactId>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<version>6.1.0</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Struts 2 Bill of Materials</name>
|
||||
@@ -44,7 +44,7 @@
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<struts-version.version>6.0.0-SNAPSHOT</struts-version.version>
|
||||
<struts-version.version>6.1.0</struts-version.version>
|
||||
<maven.site.skip>true</maven.site.skip>
|
||||
<maven.site.deploy.skip>true</maven.site.deploy.skip>
|
||||
</properties>
|
||||
@@ -56,6 +56,11 @@
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<version>${struts-version.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-async-plugin</artifactId>
|
||||
<version>${struts-version.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-bean-validation-plugin</artifactId>
|
||||
@@ -171,11 +176,16 @@
|
||||
<artifactId>struts2-tiles-plugin</artifactId>
|
||||
<version>${struts-version.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-velocity-plugin</artifactId>
|
||||
<version>${struts-version.version}</version>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</dependencyManagement>
|
||||
|
||||
<scm>
|
||||
<tag>HEAD</tag>
|
||||
<tag>STRUTS_6_1_0</tag>
|
||||
<connection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</connection>
|
||||
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/struts.git</developerConnection>
|
||||
<url>https://github.com/apache/struts/</url>
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<version>6.1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-admin-bundle</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<name>DEPRECATED: Struts 2 OSGi Admin Bundle - since 2.6</name>
|
||||
<name>DEPRECATED: Struts 2 OSGi Admin Bundle - since 6.0.0</name>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
|
||||
@@ -22,13 +22,13 @@
|
||||
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<constant name="struts.enable.DynamicMethodInvocation" value="false" />
|
||||
<package name="bundle-admin" namespace="/osgi/admin" extends="osgi-default" strict-method-invocation="true">
|
||||
<default-action-ref name="bundles" />
|
||||
|
||||
|
||||
<action name="bundle_*!*" class="org.apache.struts2.osgi.admin.actions.BundlesAction" method="{2}">
|
||||
<param name="id">{1}</param>
|
||||
<result type="freemarker">viewBundle.ftl</result>
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<version>6.1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-demo-bundle</artifactId>
|
||||
<packaging>bundle</packaging>
|
||||
<name>DEPRECATED: Struts 2 OSGi Demo Bundle - since 2.6</name>
|
||||
<name>DEPRECATED: Struts 2 OSGi Demo Bundle - since 6.0.0</name>
|
||||
|
||||
<dependencies>
|
||||
|
||||
|
||||
@@ -21,11 +21,11 @@
|
||||
-->
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.5//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
"https://struts.apache.org/dtds/struts-2.5.dtd">
|
||||
|
||||
<struts>
|
||||
<!-- Set some Struts 2 constants relevant to the OSGi Plugin.
|
||||
Note: The constant definitions specified here (within the demo bundle) may also need to be
|
||||
<!-- Set some Struts 2 constants relevant to the OSGi Plugin.
|
||||
Note: The constant definitions specified here (within the demo bundle) may also need to be
|
||||
duplicated in the struts.xml configuration of the outer project that packages the demo
|
||||
bundle JAR file within it.
|
||||
-->
|
||||
@@ -52,4 +52,4 @@
|
||||
</action>
|
||||
|
||||
</package>
|
||||
</struts>
|
||||
</struts>
|
||||
|
||||
+3
-5
@@ -24,12 +24,12 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<version>6.1.0</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
<name>DEPRECATED: Struts 2 OSGi Bundles - since 2.6</name>
|
||||
<name>DEPRECATED: Struts 2 OSGi Bundles - since 6.0.0</name>
|
||||
|
||||
<modules>
|
||||
<module>admin</module>
|
||||
@@ -53,12 +53,10 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.4</version>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
<reporting>
|
||||
|
||||
@@ -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
|
||||
+15
-17
@@ -24,14 +24,14 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>6.0.0-SNAPSHOT</version>
|
||||
<version>6.1.0</version>
|
||||
</parent>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Struts 2 Core</name>
|
||||
|
||||
<properties>
|
||||
<tlib.version>2.6</tlib.version>
|
||||
<tlib.version>6.0</tlib.version>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
@@ -41,6 +41,7 @@
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<argLine>@{argLine}</argLine>
|
||||
<properties>
|
||||
<property>
|
||||
<name>maven.testng.output.dir</name>
|
||||
@@ -54,9 +55,6 @@
|
||||
<element>${project.build.testOutputDirectory}/xwork - jar.jar</element>
|
||||
<element>${project.build.testOutputDirectory}/xwork - zip.zip</element>
|
||||
</additionalClasspathElements>
|
||||
<includes>
|
||||
<include>**/*Test.java</include>
|
||||
</includes>
|
||||
<excludes>
|
||||
<exclude>**/XWorkTestCase.java</exclude>
|
||||
<exclude>**/TestBean.java</exclude>
|
||||
@@ -188,7 +186,7 @@
|
||||
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
@@ -242,6 +240,16 @@
|
||||
<artifactId>spring-web</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-context-support</artifactId>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
@@ -329,8 +337,7 @@
|
||||
<dependency>
|
||||
<groupId>org.testng</groupId>
|
||||
<artifactId>testng</artifactId>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- SLF4J support -->
|
||||
@@ -345,15 +352,6 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- The Servlet API mocks in Spring Framework 4.x only supports Servlet 3.0 and higher.
|
||||
This is only necessary in tests-->
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>javax.servlet-api</artifactId>
|
||||
<version>3.1.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-validator</groupId>
|
||||
<artifactId>commons-validator</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@ 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 2.6
|
||||
* @since 6.0.0
|
||||
*/
|
||||
public interface AsyncManager {
|
||||
boolean hasAsyncActionResult();
|
||||
|
||||
@@ -73,7 +73,7 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
protected UnknownHandlerManager unknownHandlerManager;
|
||||
protected OgnlUtil ognlUtil;
|
||||
protected AsyncManager asyncManager;
|
||||
protected Callable asyncAction;
|
||||
protected Callable<?> asyncAction;
|
||||
protected WithLazyParams.LazyParamInjector lazyParamInjector;
|
||||
|
||||
public DefaultActionInvocation(final Map<String, Object> extraContext, final boolean pushAction) {
|
||||
@@ -101,7 +101,7 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
this.container = cont;
|
||||
}
|
||||
|
||||
@Inject(required=false)
|
||||
@Inject(required = false)
|
||||
public void setActionEventListener(ActionEventListener listener) {
|
||||
this.actionEventListener = listener;
|
||||
}
|
||||
@@ -111,7 +111,7 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
this.ognlUtil = ognlUtil;
|
||||
}
|
||||
|
||||
@Inject(required=false)
|
||||
@Inject(required = false)
|
||||
public void setAsyncManager(AsyncManager asyncManager) {
|
||||
this.asyncManager = asyncManager;
|
||||
}
|
||||
@@ -214,7 +214,7 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
} 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("*");
|
||||
@@ -248,7 +248,12 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
if (interceptor instanceof WithLazyParams) {
|
||||
interceptor = lazyParamInjector.injectParams(interceptor, interceptorMapping.getParams(), invocationContext);
|
||||
}
|
||||
resultCode = interceptor.intercept(DefaultActionInvocation.this);
|
||||
if (interceptor.isDisabled(this)) {
|
||||
LOG.debug("Interceptor: {} is disabled, skipping to next", interceptor.getClass().getSimpleName());
|
||||
resultCode = this.invoke();
|
||||
} else {
|
||||
resultCode = interceptor.intercept(this);
|
||||
}
|
||||
} else {
|
||||
resultCode = invokeActionOnly();
|
||||
}
|
||||
@@ -268,9 +273,7 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
if (preResultListeners != null) {
|
||||
LOG.trace("Executing PreResultListeners for result [{}]", result);
|
||||
|
||||
for (Object preResultListener : preResultListeners) {
|
||||
PreResultListener listener = (PreResultListener) preResultListener;
|
||||
|
||||
for (PreResultListener listener : preResultListeners) {
|
||||
listener.beforeResult(this, resultCode);
|
||||
}
|
||||
}
|
||||
@@ -314,7 +317,7 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
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]");
|
||||
gripe += e.getMessage();
|
||||
throw new StrutsException(gripe, e, proxy.getConfig());
|
||||
}
|
||||
|
||||
@@ -363,7 +366,7 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
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());
|
||||
+ " and result " + getResultCode(), proxy.getConfig());
|
||||
} else {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("No result returned for action {} at {}", getAction().getClass().getName(), proxy.getConfig().getLocation());
|
||||
@@ -464,6 +467,7 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
|
||||
/**
|
||||
* Save the result to be used later.
|
||||
*
|
||||
* @param actionConfig current ActionConfig
|
||||
* @param methodResult the result of the action.
|
||||
* @return the result code to process.
|
||||
@@ -476,7 +480,7 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
container.inject(explicitResult);
|
||||
return null;
|
||||
} else if (methodResult instanceof Callable) {
|
||||
asyncAction = (Callable) methodResult;
|
||||
asyncAction = (Callable<?>) methodResult;
|
||||
return null;
|
||||
} else {
|
||||
return (String) methodResult;
|
||||
|
||||
@@ -34,22 +34,22 @@ import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Base JUnit TestCase to extend for XWork specific JUnit tests. Uses
|
||||
* 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();
|
||||
@@ -57,7 +57,7 @@ public abstract class XWorkTestCase extends TestCase {
|
||||
container = configuration.getContainer();
|
||||
actionProxyFactory = container.getInstance(ActionProxyFactory.class);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void tearDown() throws Exception {
|
||||
XWorkTestCaseHelper.tearDown(configurationManager);
|
||||
@@ -66,34 +66,33 @@ public abstract class XWorkTestCase extends TestCase {
|
||||
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) {
|
||||
|
||||
protected <T> void loadButAdd(final Class<T> type, final T impl) {
|
||||
loadButAdd(type, Container.DEFAULT_NAME, impl);
|
||||
}
|
||||
|
||||
protected void loadButAdd(final Class<?> type, final String name, final Object impl) {
|
||||
|
||||
protected <T> void loadButAdd(final Class<T> type, final String name, final T impl) {
|
||||
loadConfigurationProviders(new StubConfigurationProvider() {
|
||||
@Override
|
||||
public void register(ContainerBuilder builder,
|
||||
LocatableProperties props) throws ConfigurationException {
|
||||
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() {
|
||||
public Object create(Context context) throws Exception {
|
||||
builder.factory(type, name, new Factory<T>() {
|
||||
public T create(Context context) throws Exception {
|
||||
return impl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return impl.getClass();
|
||||
public Class<T> type() {
|
||||
return (Class<T>) impl.getClass();
|
||||
}
|
||||
}, Scope.SINGLETON);
|
||||
}
|
||||
|
||||
@@ -20,26 +20,18 @@ package com.opensymphony.xwork2.config.entities;
|
||||
|
||||
import com.opensymphony.xwork2.util.location.Located;
|
||||
import com.opensymphony.xwork2.util.location.Location;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.*;
|
||||
|
||||
|
||||
/**
|
||||
* Configuration for Package.
|
||||
*
|
||||
* <p>
|
||||
* In the xml configuration file this is defined as the <code>package</code> tag.
|
||||
* </p>
|
||||
*
|
||||
* @author Rainer Hermanns
|
||||
* @version $Revision$
|
||||
*/
|
||||
public class PackageConfig extends Located implements Comparable, Serializable, InterceptorLocator {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(PackageConfig.class);
|
||||
public class PackageConfig extends Located implements Comparable<PackageConfig>, Serializable, InterceptorLocator {
|
||||
|
||||
protected Map<String, ActionConfig> actionConfigs;
|
||||
protected Map<String, ResultConfig> globalResultConfigs;
|
||||
@@ -422,8 +414,7 @@ public class PackageConfig extends Located implements Comparable, Serializable,
|
||||
return "PackageConfig: [" + name + "] for namespace [" + namespace + "] with parents [" + parents + "]";
|
||||
}
|
||||
|
||||
public int compareTo(Object o) {
|
||||
PackageConfig other = (PackageConfig) o;
|
||||
public int compareTo(PackageConfig other) {
|
||||
String full = namespace + "!" + name;
|
||||
String otherFull = other.namespace + "!" + other.name;
|
||||
|
||||
@@ -443,7 +434,6 @@ public class PackageConfig extends Located implements Comparable, Serializable,
|
||||
public static class Builder implements InterceptorLocator {
|
||||
|
||||
protected PackageConfig target;
|
||||
private boolean strictDMI = true;
|
||||
|
||||
public Builder(String name) {
|
||||
target = new PackageConfig(name);
|
||||
|
||||
@@ -298,8 +298,8 @@ public class DefaultConfiguration implements Configuration {
|
||||
|
||||
builder.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON);
|
||||
builder.factory(PropertyAccessor.class, CompoundRoot.class.getName(), CompoundRootAccessor.class, Scope.SINGLETON);
|
||||
builder.factory(ExpressionCacheFactory.class, "defaultOgnlExpressionCacheFactory", DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON);
|
||||
builder.factory(BeanInfoCacheFactory.class, "defaultOgnlBeanInfoCacheFactory", DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON);
|
||||
builder.factory(ExpressionCacheFactory.class, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON);
|
||||
builder.factory(BeanInfoCacheFactory.class, DefaultOgnlBeanInfoCacheFactory.class, Scope.SINGLETON);
|
||||
builder.factory(OgnlUtil.class, Scope.SINGLETON);
|
||||
|
||||
builder.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON);
|
||||
|
||||
+99
-93
@@ -21,26 +21,16 @@ 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.StrutsTextProviderFactory;
|
||||
import com.opensymphony.xwork2.TextProviderFactory;
|
||||
import com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory;
|
||||
import com.opensymphony.xwork2.factory.UnknownHandlerFactory;
|
||||
import com.opensymphony.xwork2.ognl.BeanInfoCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.ExpressionCacheFactory;
|
||||
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.DefaultTextProvider;
|
||||
import com.opensymphony.xwork2.DefaultUnknownHandlerManager;
|
||||
import com.opensymphony.xwork2.security.DefaultNotExcludedAcceptedPatternsChecker;
|
||||
import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
|
||||
import com.opensymphony.xwork2.FileManager;
|
||||
import com.opensymphony.xwork2.FileManagerFactory;
|
||||
import com.opensymphony.xwork2.LocaleProviderFactory;
|
||||
import com.opensymphony.xwork2.LocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.ObjectFactory;
|
||||
import com.opensymphony.xwork2.StrutsTextProviderFactory;
|
||||
import com.opensymphony.xwork2.TextProvider;
|
||||
import com.opensymphony.xwork2.TextProviderFactory;
|
||||
import com.opensymphony.xwork2.UnknownHandlerManager;
|
||||
import com.opensymphony.xwork2.config.Configuration;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
@@ -57,14 +47,7 @@ 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.security.NotExcludedAcceptedPatternsChecker;
|
||||
import org.apache.struts2.components.date.DateFormatter;
|
||||
import org.apache.struts2.components.date.DateTimeFormatterAdapter;
|
||||
import org.apache.struts2.components.date.SimpleDateFormatAdapter;
|
||||
import org.apache.struts2.conversion.StrutsConversionPropertiesProcessor;
|
||||
import com.opensymphony.xwork2.conversion.impl.DefaultObjectTypeDeterminer;
|
||||
import org.apache.struts2.conversion.StrutsTypeConverterCreator;
|
||||
import org.apache.struts2.conversion.StrutsTypeConverterHolder;
|
||||
import com.opensymphony.xwork2.conversion.impl.InstantiatingNullHandler;
|
||||
import com.opensymphony.xwork2.conversion.impl.NumberConverter;
|
||||
import com.opensymphony.xwork2.conversion.impl.StringConverter;
|
||||
@@ -73,34 +56,45 @@ 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.StrutsConverterFactory;
|
||||
import com.opensymphony.xwork2.factory.DefaultInterceptorFactory;
|
||||
import com.opensymphony.xwork2.factory.DefaultResultFactory;
|
||||
import com.opensymphony.xwork2.factory.DefaultUnknownHandlerFactory;
|
||||
import com.opensymphony.xwork2.factory.InterceptorFactory;
|
||||
import com.opensymphony.xwork2.factory.ResultFactory;
|
||||
import com.opensymphony.xwork2.factory.StrutsConverterFactory;
|
||||
import com.opensymphony.xwork2.factory.UnknownHandlerFactory;
|
||||
import com.opensymphony.xwork2.inject.ContainerBuilder;
|
||||
import com.opensymphony.xwork2.inject.Scope;
|
||||
import com.opensymphony.xwork2.ognl.BeanInfoCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.ExpressionCacheFactory;
|
||||
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.HttpParametersPropertyAccessor;
|
||||
import com.opensymphony.xwork2.ognl.accessor.ObjectAccessor;
|
||||
import com.opensymphony.xwork2.ognl.accessor.ObjectProxyPropertyAccessor;
|
||||
import com.opensymphony.xwork2.ognl.accessor.ParameterPropertyAccessor;
|
||||
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.security.AcceptedPatternsChecker;
|
||||
import com.opensymphony.xwork2.security.DefaultAcceptedPatternsChecker;
|
||||
import com.opensymphony.xwork2.security.DefaultExcludedPatternsChecker;
|
||||
import com.opensymphony.xwork2.security.DefaultNotExcludedAcceptedPatternsChecker;
|
||||
import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
|
||||
import com.opensymphony.xwork2.security.NotExcludedAcceptedPatternsChecker;
|
||||
import com.opensymphony.xwork2.util.CompoundRoot;
|
||||
import com.opensymphony.xwork2.LocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.ognl.DefaultOgnlBeanInfoCacheFactory;
|
||||
import com.opensymphony.xwork2.ognl.DefaultOgnlExpressionCacheFactory;
|
||||
import com.opensymphony.xwork2.util.StrutsLocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.util.OgnlTextParser;
|
||||
import com.opensymphony.xwork2.util.PatternMatcher;
|
||||
import com.opensymphony.xwork2.util.StrutsLocalizedTextProvider;
|
||||
import com.opensymphony.xwork2.util.TextParser;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
import com.opensymphony.xwork2.util.WildcardHelper;
|
||||
@@ -119,8 +113,19 @@ import com.opensymphony.xwork2.validator.ValidatorFileParser;
|
||||
import ognl.MethodAccessor;
|
||||
import ognl.PropertyAccessor;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.conversion.StrutsConversionPropertiesProcessor;
|
||||
import org.apache.struts2.conversion.StrutsTypeConverterCreator;
|
||||
import org.apache.struts2.conversion.StrutsTypeConverterHolder;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
import org.apache.struts2.dispatcher.Parameter;
|
||||
import org.apache.struts2.url.QueryStringBuilder;
|
||||
import org.apache.struts2.url.QueryStringParser;
|
||||
import org.apache.struts2.url.StrutsQueryStringBuilder;
|
||||
import org.apache.struts2.url.StrutsQueryStringParser;
|
||||
import org.apache.struts2.url.StrutsUrlDecoder;
|
||||
import org.apache.struts2.url.StrutsUrlEncoder;
|
||||
import org.apache.struts2.url.UrlDecoder;
|
||||
import org.apache.struts2.url.UrlEncoder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
@@ -153,88 +158,90 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider
|
||||
|
||||
@Override
|
||||
public void register(ContainerBuilder builder, LocatableProperties props)
|
||||
throws ConfigurationException {
|
||||
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, StrutsConverterFactory.class)
|
||||
.factory(UnknownHandlerFactory.class, DefaultUnknownHandlerFactory.class)
|
||||
.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, StrutsConverterFactory.class)
|
||||
.factory(UnknownHandlerFactory.class, DefaultUnknownHandlerFactory.class)
|
||||
|
||||
.factory(ActionProxyFactory.class, DefaultActionProxyFactory.class, Scope.SINGLETON)
|
||||
.factory(ObjectTypeDeterminer.class, DefaultObjectTypeDeterminer.class, Scope.SINGLETON)
|
||||
.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, StrutsConversionPropertiesProcessor.class, Scope.SINGLETON)
|
||||
.factory(ConversionFileProcessor.class, DefaultConversionFileProcessor.class, Scope.SINGLETON)
|
||||
.factory(ConversionAnnotationProcessor.class, DefaultConversionAnnotationProcessor.class, Scope.SINGLETON)
|
||||
.factory(TypeConverterCreator.class, StrutsTypeConverterCreator.class, Scope.SINGLETON)
|
||||
.factory(TypeConverterHolder.class, StrutsTypeConverterHolder.class, Scope.SINGLETON)
|
||||
.factory(XWorkConverter.class, Scope.SINGLETON)
|
||||
.factory(XWorkBasicConverter.class, Scope.SINGLETON)
|
||||
.factory(ConversionPropertiesProcessor.class, StrutsConversionPropertiesProcessor.class, Scope.SINGLETON)
|
||||
.factory(ConversionFileProcessor.class, DefaultConversionFileProcessor.class, Scope.SINGLETON)
|
||||
.factory(ConversionAnnotationProcessor.class, DefaultConversionAnnotationProcessor.class, Scope.SINGLETON)
|
||||
.factory(TypeConverterCreator.class, StrutsTypeConverterCreator.class, Scope.SINGLETON)
|
||||
.factory(TypeConverterHolder.class, StrutsTypeConverterHolder.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(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(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)
|
||||
.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)
|
||||
// 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(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(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(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(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON)
|
||||
.factory(LocalizedTextProvider.class, StrutsLocalizedTextProvider.class, Scope.SINGLETON)
|
||||
.factory(TextProviderFactory.class, StrutsTextProviderFactory.class, Scope.SINGLETON)
|
||||
.factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON)
|
||||
.factory(TextProvider.class, "system", DefaultTextProvider.class, Scope.SINGLETON)
|
||||
.factory(LocalizedTextProvider.class, StrutsLocalizedTextProvider.class, Scope.SINGLETON)
|
||||
.factory(TextProviderFactory.class, StrutsTextProviderFactory.class, Scope.SINGLETON)
|
||||
.factory(LocaleProviderFactory.class, DefaultLocaleProviderFactory.class, Scope.SINGLETON)
|
||||
|
||||
.factory(ExpressionCacheFactory.class, "defaultOgnlExpressionCacheFactory", DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON)
|
||||
.factory(BeanInfoCacheFactory.class, "defaultOgnlBeanInfoCacheFactory", DefaultOgnlBeanInfoCacheFactory.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(ExpressionCacheFactory.class, DefaultOgnlExpressionCacheFactory.class, Scope.SINGLETON)
|
||||
.factory(BeanInfoCacheFactory.class, DefaultOgnlBeanInfoCacheFactory.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(NotExcludedAcceptedPatternsChecker.class, DefaultNotExcludedAcceptedPatternsChecker.class
|
||||
, Scope.SINGLETON)
|
||||
.factory(ExcludedPatternsChecker.class, DefaultExcludedPatternsChecker.class, Scope.PROTOTYPE)
|
||||
.factory(AcceptedPatternsChecker.class, DefaultAcceptedPatternsChecker.class, Scope.PROTOTYPE)
|
||||
.factory(NotExcludedAcceptedPatternsChecker.class, DefaultNotExcludedAcceptedPatternsChecker.class
|
||||
, Scope.SINGLETON)
|
||||
|
||||
.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON)
|
||||
.factory(ValueSubstitutor.class, EnvsValueSubstitutor.class, Scope.SINGLETON)
|
||||
|
||||
.factory(DateFormatter.class, "simpleDateFormatter", SimpleDateFormatAdapter.class, Scope.SINGLETON)
|
||||
.factory(DateFormatter.class, "dateTimeFormatter", DateTimeFormatterAdapter.class, Scope.SINGLETON)
|
||||
.factory(QueryStringBuilder.class, StrutsQueryStringBuilder.class, Scope.SINGLETON)
|
||||
.factory(QueryStringParser.class, StrutsQueryStringParser.class, Scope.SINGLETON)
|
||||
.factory(UrlEncoder.class, StrutsUrlEncoder.class, Scope.SINGLETON)
|
||||
.factory(UrlDecoder.class, StrutsUrlDecoder.class, Scope.SINGLETON)
|
||||
;
|
||||
|
||||
props.setProperty(StrutsConstants.STRUTS_ENABLE_DYNAMIC_METHOD_INVOCATION, Boolean.FALSE.toString());
|
||||
@@ -244,7 +251,6 @@ public class StrutsDefaultConfigurationProvider implements ConfigurationProvider
|
||||
props.setProperty(StrutsConstants.STRUTS_OGNL_ENABLE_EXPRESSION_CACHE, Boolean.TRUE.toString());
|
||||
props.setProperty(StrutsConstants.STRUTS_OGNL_ENABLE_EVAL_EXPRESSION, Boolean.FALSE.toString());
|
||||
props.setProperty(StrutsConstants.STRUTS_CONFIGURATION_XML_RELOAD, Boolean.FALSE.toString());
|
||||
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, Boolean.FALSE.toString());
|
||||
props.setProperty(StrutsConstants.STRUTS_ALLOW_STATIC_FIELD_ACCESS, Boolean.TRUE.toString());
|
||||
props.setProperty(StrutsConstants.STRUTS_MATCHER_APPEND_NAMED_PARAMETERS, Boolean.TRUE.toString());
|
||||
}
|
||||
|
||||
@@ -18,28 +18,36 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2.conversion.impl;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.conversion.TypeConversionException;
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.TextProvider;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Member;
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.time.LocalDate;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.LocalTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.time.format.DateTimeParseException;
|
||||
import java.time.temporal.TemporalAccessor;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.conversion.TypeConversionException;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.TextProvider;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
|
||||
public class DateConverter extends DefaultTypeConverter {
|
||||
|
||||
private final static Logger LOG = LogManager.getLogger(DateConverter.class);
|
||||
|
||||
@Override
|
||||
public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName, Object value, Class toType) {
|
||||
public Object convertValue(Map<String, Object> context, Object target, Member member, String propertyName,
|
||||
Object value, Class toType) {
|
||||
Date result = null;
|
||||
|
||||
if (value instanceof String && ((String) value).length() > 0) {
|
||||
@@ -52,15 +60,12 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
} 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);
|
||||
DateFormat.MEDIUM, locale);
|
||||
SimpleDateFormat fullfmt = new SimpleDateFormat(dtfmt.toPattern() + MILLISECOND_FORMAT, locale);
|
||||
|
||||
SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT,
|
||||
locale);
|
||||
SimpleDateFormat dfmt = (SimpleDateFormat) DateFormat.getDateInstance(DateFormat.SHORT, locale);
|
||||
|
||||
SimpleDateFormat[] fmts = {fullfmt, dtfmt, dfmt};
|
||||
SimpleDateFormat[] fmts = { fullfmt, dtfmt, dfmt };
|
||||
for (SimpleDateFormat fmt : fmts) {
|
||||
try {
|
||||
check = fmt.parse(sa);
|
||||
@@ -85,8 +90,39 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
} catch (ParseException ignore) {
|
||||
}
|
||||
}
|
||||
} else if (java.time.LocalDateTime.class == toType || java.time.LocalDate.class == toType
|
||||
|| java.time.LocalTime.class == toType) {
|
||||
DateTimeFormatter dtf = null;
|
||||
TemporalAccessor check = null;
|
||||
DateTimeFormatter[] dfs = getDateTimeFormats(ActionContext.of(context), locale);
|
||||
|
||||
for (DateTimeFormatter df1 : dfs) {
|
||||
try {
|
||||
check = df1.parseBest(sa, LocalDateTime::from, LocalDate::from, LocalTime::from);
|
||||
dtf = df1;
|
||||
if (check != null) {
|
||||
break;
|
||||
}
|
||||
} catch (DateTimeParseException ignore) {
|
||||
}
|
||||
}
|
||||
try {
|
||||
if (dtf != null && check instanceof LocalDateTime) {
|
||||
return LocalDateTime.parse(sa, dtf);
|
||||
} else if (dtf != null && check instanceof LocalDate) {
|
||||
return LocalDate.parse(sa, dtf);
|
||||
} else if (dtf != null && check instanceof LocalTime) {
|
||||
return LocalTime.parse(sa, dtf);
|
||||
} else {
|
||||
throw new TypeConversionException("Could not parse date");
|
||||
}
|
||||
} catch (DateTimeParseException e) {
|
||||
throw new TypeConversionException("Could not parse date", e);
|
||||
}
|
||||
|
||||
}
|
||||
//final fallback for dates without time
|
||||
|
||||
// final fallback for dates without time
|
||||
if (df == null) {
|
||||
df = DateFormat.getDateInstance(DateFormat.SHORT, locale);
|
||||
}
|
||||
@@ -95,15 +131,17 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
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())});
|
||||
Constructor<?> constructor = toType.getConstructor(new Class[] { long.class });
|
||||
return constructor.newInstance(new Object[] { Long.valueOf(result.getTime()) });
|
||||
} catch (Exception e) {
|
||||
throw new TypeConversionException("Couldn't create class " + toType + " using default (long) constructor", e);
|
||||
throw new TypeConversionException(
|
||||
"Couldn't create class " + toType + " using default (long) constructor", e);
|
||||
}
|
||||
}
|
||||
} catch (ParseException e) {
|
||||
throw new TypeConversionException("Could not parse date", e);
|
||||
}
|
||||
|
||||
} else if (Date.class.isAssignableFrom(value.getClass())) {
|
||||
result = (Date) value;
|
||||
}
|
||||
@@ -111,16 +149,16 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
}
|
||||
|
||||
/**
|
||||
* The user defined global date format,
|
||||
* see {@link org.apache.struts2.components.Date#DATETAG_PROPERTY}
|
||||
* The user defined global date format, see
|
||||
* {@link org.apache.struts2.components.Date#DATETAG_PROPERTY}
|
||||
*
|
||||
* @param context current ActionContext
|
||||
* @param locale current Locale to convert to
|
||||
* @return defined global format
|
||||
*
|
||||
* @return defined global date string format
|
||||
*/
|
||||
protected DateFormat getGlobalDateFormat(ActionContext context, Locale locale) {
|
||||
protected String getGlobalDateString(ActionContext context) {
|
||||
final String dateTagProperty = org.apache.struts2.components.Date.DATETAG_PROPERTY;
|
||||
SimpleDateFormat globalDateFormat = null;
|
||||
String globalDateString = null;
|
||||
|
||||
final TextProvider tp = findProviderInStack(context.getValueStack());
|
||||
|
||||
@@ -130,23 +168,28 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
// is the same as input = DATETAG_PROPERTY
|
||||
if (globalFormat != null && !dateTagProperty.equals(globalFormat)) {
|
||||
LOG.debug("Found \"{}\" as \"{}\"", dateTagProperty, globalFormat);
|
||||
globalDateFormat = new SimpleDateFormat(globalFormat, locale);
|
||||
globalDateString = globalFormat;
|
||||
} else {
|
||||
LOG.debug("\"{}\" has not been defined, ignoring it", dateTagProperty);
|
||||
}
|
||||
}
|
||||
|
||||
return globalDateFormat;
|
||||
return globalDateString;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of date formats to be used when converting dates
|
||||
*
|
||||
* @param context the current ActionContext
|
||||
* @param locale the current locale of the action
|
||||
* @param locale the current locale of the action
|
||||
* @return a list of DateFormat to be used for date conversion
|
||||
*/
|
||||
private DateFormat[] getDateFormats(ActionContext context, Locale locale) {
|
||||
DateFormat globalDateFormat = getGlobalDateFormat(context, locale);
|
||||
DateFormat globalDateFormat = null;
|
||||
String globalFormat = getGlobalDateString(context);
|
||||
if (globalFormat != null) {
|
||||
globalDateFormat = new SimpleDateFormat(globalFormat, locale);
|
||||
}
|
||||
|
||||
DateFormat dt1 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.LONG, locale);
|
||||
DateFormat dt2 = DateFormat.getDateTimeInstance(DateFormat.SHORT, DateFormat.MEDIUM, locale);
|
||||
@@ -156,15 +199,46 @@ public class DateConverter extends DefaultTypeConverter {
|
||||
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 rfc3339 = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss");
|
||||
DateFormat rfc3339dateOnly = new SimpleDateFormat("yyyy-MM-dd");
|
||||
|
||||
final DateFormat[] dateFormats;
|
||||
|
||||
if (globalDateFormat == null) {
|
||||
dateFormats = new DateFormat[]{dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly};
|
||||
dateFormats = new DateFormat[] { dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly };
|
||||
} else {
|
||||
dateFormats = new DateFormat[]{globalDateFormat, dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly};
|
||||
dateFormats = new DateFormat[] { globalDateFormat, dt1, dt2, dt3, rfc3339, d1, d2, d3, rfc3339dateOnly };
|
||||
}
|
||||
|
||||
return dateFormats;
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the list of date time formats to be used when converting dates
|
||||
*
|
||||
* @param context the current ActionContext
|
||||
* @param locale the current locale of the action
|
||||
*
|
||||
* @return a list of DateTimeFormatter to be used for date conversion
|
||||
*/
|
||||
protected DateTimeFormatter[] getDateTimeFormats(ActionContext context, Locale locale) {
|
||||
|
||||
DateTimeFormatter globalDateFormat = null;
|
||||
String globalFormat = getGlobalDateString(context);
|
||||
if (globalFormat != null) {
|
||||
globalDateFormat = DateTimeFormatter.ofPattern(globalFormat, locale);
|
||||
}
|
||||
|
||||
DateTimeFormatter df1 = DateTimeFormatter.ISO_LOCAL_DATE_TIME;
|
||||
DateTimeFormatter df2 = DateTimeFormatter.ISO_LOCAL_DATE;
|
||||
DateTimeFormatter df3 = DateTimeFormatter.ISO_LOCAL_TIME;
|
||||
|
||||
final DateTimeFormatter[] dateFormats;
|
||||
|
||||
if (globalDateFormat == null) {
|
||||
dateFormats = new DateTimeFormatter[] { df1, df2, df3 };
|
||||
} else {
|
||||
dateFormats = new DateTimeFormatter[] { globalDateFormat, df1, df2, df3 };
|
||||
}
|
||||
|
||||
return dateFormats;
|
||||
|
||||
@@ -25,6 +25,7 @@ import com.opensymphony.xwork2.inject.Inject;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
|
||||
import java.lang.reflect.Member;
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Date;
|
||||
@@ -99,6 +100,8 @@ public class XWorkBasicConverter extends DefaultTypeConverter {
|
||||
result = doConvertToArray(context, o, member, propertyName, value, toType);
|
||||
} else if (Date.class.isAssignableFrom(toType)) {
|
||||
result = doConvertToDate(context, value, toType);
|
||||
} else if (LocalDateTime.class.isAssignableFrom(toType)) {
|
||||
result = doConvertToDate(context, value, toType);
|
||||
} else if (Calendar.class.isAssignableFrom(toType)) {
|
||||
result = doConvertToCalendar(context, value);
|
||||
} else if (Collection.class.isAssignableFrom(toType)) {
|
||||
|
||||
@@ -19,10 +19,26 @@ import com.opensymphony.xwork2.inject.util.ReferenceCache;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.*;
|
||||
import java.lang.reflect.AccessibleObject;
|
||||
import java.lang.reflect.AnnotatedElement;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.InvocationTargetException;
|
||||
import java.lang.reflect.Member;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.lang.reflect.ReflectPermission;
|
||||
import java.security.AccessControlException;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* Default {@link Container} implementation.
|
||||
@@ -39,11 +55,7 @@ class ContainerImpl implements Container {
|
||||
this.factories = factories;
|
||||
final Map<Class<?>, Set<String>> map = new HashMap<>();
|
||||
for (Key<?> key : factories.keySet()) {
|
||||
Set<String> names = map.get(key.getType());
|
||||
if (names == null) {
|
||||
names = new HashSet<>();
|
||||
map.put(key.getType(), names);
|
||||
}
|
||||
Set<String> names = map.computeIfAbsent(key.getType(), k -> new HashSet<>());
|
||||
names.add(key.getName());
|
||||
}
|
||||
|
||||
@@ -63,20 +75,20 @@ class ContainerImpl implements Container {
|
||||
* Field and method injectors.
|
||||
*/
|
||||
final Map<Class<?>, List<Injector>> injectors =
|
||||
new ReferenceCache<Class<?>, List<Injector>>() {
|
||||
@Override
|
||||
protected List<Injector> create(Class<?> key) {
|
||||
List<Injector> injectors = new ArrayList<>();
|
||||
addInjectors(key, injectors);
|
||||
return injectors;
|
||||
}
|
||||
};
|
||||
new ReferenceCache<Class<?>, List<Injector>>() {
|
||||
@Override
|
||||
protected List<Injector> create(Class<?> key) {
|
||||
List<Injector> 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<Injector> injectors) {
|
||||
void addInjectors(Class<?> clazz, List<Injector> injectors) {
|
||||
if (clazz == Object.class) {
|
||||
return;
|
||||
}
|
||||
@@ -97,38 +109,24 @@ class ContainerImpl implements Container {
|
||||
addInjectorsForMethods(clazz.getDeclaredMethods(), true, injectors);
|
||||
}
|
||||
|
||||
callInContext(new ContextualCallable<Void>() {
|
||||
public Void call(InternalContext context) {
|
||||
for (Injector injector : injectors) {
|
||||
injector.inject(context, null);
|
||||
}
|
||||
return null;
|
||||
callInContext((ContextualCallable<Void>) context -> {
|
||||
for (Injector injector : injectors) {
|
||||
injector.inject(context, null);
|
||||
}
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
void addInjectorsForMethods(Method[] methods, boolean statics, List<Injector> injectors) {
|
||||
addInjectorsForMembers(Arrays.asList(methods), statics, injectors,
|
||||
new InjectorFactory<Method>() {
|
||||
public Injector create(ContainerImpl container, Method method,
|
||||
String name) throws MissingDependencyException {
|
||||
return new MethodInjector(container, method, name);
|
||||
}
|
||||
});
|
||||
addInjectorsForMembers(Arrays.asList(methods), statics, injectors, MethodInjector::new);
|
||||
}
|
||||
|
||||
void addInjectorsForFields(Field[] fields, boolean statics, List<Injector> injectors) {
|
||||
addInjectorsForMembers(Arrays.asList(fields), statics, injectors,
|
||||
new InjectorFactory<Field>() {
|
||||
public Injector create(ContainerImpl container, Field field,
|
||||
String name) throws MissingDependencyException {
|
||||
return new FieldInjector(container, field, name);
|
||||
}
|
||||
});
|
||||
addInjectorsForMembers(Arrays.asList(fields), statics, injectors, FieldInjector::new);
|
||||
}
|
||||
|
||||
<M extends Member & AnnotatedElement> void addInjectorsForMembers(
|
||||
List<M> members, boolean statics, List<Injector> injectors, InjectorFactory<M> injectorFactory) {
|
||||
List<M> members, boolean statics, List<Injector> injectors, InjectorFactory<M> injectorFactory) {
|
||||
for (M member : members) {
|
||||
if (isStatic(member) == statics) {
|
||||
Inject inject = member.getAnnotation(Inject.class);
|
||||
@@ -148,12 +146,12 @@ class ContainerImpl implements Container {
|
||||
interface InjectorFactory<M extends Member & AnnotatedElement> {
|
||||
|
||||
Injector create(ContainerImpl container, M member, String name)
|
||||
throws MissingDependencyException;
|
||||
throws MissingDependencyException;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if a given {@link Member} is static or not.
|
||||
*
|
||||
*
|
||||
* @param member checked for the static modifier.
|
||||
* @return true if member is static, false otherwise.
|
||||
*/
|
||||
@@ -163,13 +161,13 @@ class ContainerImpl implements Container {
|
||||
|
||||
/**
|
||||
* Determines if a given {@link Member} is considered to be public for reflection usage or not.
|
||||
*
|
||||
*
|
||||
* @param member checked to see if it is public for reflection usage.
|
||||
* @return true if member is public for reflection usage, false otherwise.
|
||||
*/
|
||||
private static boolean isPublicForReflection(Member member) {
|
||||
return Modifier.isPublic(member.getModifiers()) &&
|
||||
Modifier.isPublic(member.getDeclaringClass().getModifiers());
|
||||
Modifier.isPublic(member.getDeclaringClass().getModifiers());
|
||||
}
|
||||
|
||||
static class FieldInjector implements Injector {
|
||||
@@ -179,7 +177,7 @@ class ContainerImpl implements Container {
|
||||
final ExternalContext<?> externalContext;
|
||||
|
||||
public FieldInjector(ContainerImpl container, Field field, String name)
|
||||
throws MissingDependencyException {
|
||||
throws MissingDependencyException {
|
||||
this.field = field;
|
||||
if (!isPublicForReflection(field) && !field.isAccessible()) {
|
||||
SecurityManager sm = System.getSecurityManager();
|
||||
@@ -190,7 +188,7 @@ class ContainerImpl implements Container {
|
||||
field.setAccessible(true);
|
||||
} catch (AccessControlException e) {
|
||||
throw new DependencyException("Security manager in use, could not access field: "
|
||||
+ field.getDeclaringClass().getName() + "(" + field.getName() + ")", e);
|
||||
+ field.getDeclaringClass().getName() + "(" + field.getName() + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -225,8 +223,12 @@ class ContainerImpl implements Container {
|
||||
* @param parameterTypes parameter types
|
||||
* @return injections
|
||||
*/
|
||||
<M extends AccessibleObject & Member> ParameterInjector<?>[]
|
||||
getParametersInjectors(M member, Annotation[][] annotations, Class[] parameterTypes, String defaultName) throws MissingDependencyException {
|
||||
<M extends AccessibleObject & Member> ParameterInjector<?>[] getParametersInjectors(
|
||||
M member,
|
||||
Annotation[][] annotations,
|
||||
Class<?>[] parameterTypes,
|
||||
String defaultName
|
||||
) throws MissingDependencyException {
|
||||
final List<ParameterInjector<?>> parameterInjectors = new ArrayList<>();
|
||||
|
||||
final Iterator<Annotation[]> annotationsIterator = Arrays.asList(annotations).iterator();
|
||||
@@ -247,12 +249,11 @@ class ContainerImpl implements Container {
|
||||
}
|
||||
|
||||
final ExternalContext<T> externalContext = ExternalContext.newInstance(member, key, this);
|
||||
return new ParameterInjector<T>(externalContext, factory);
|
||||
return new ParameterInjector<>(externalContext, factory);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private ParameterInjector<?>[] toArray(List<ParameterInjector<?>> parameterInjections) {
|
||||
return parameterInjections.toArray(new ParameterInjector[parameterInjections.size()]);
|
||||
return parameterInjections.toArray(new ParameterInjector[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -261,7 +262,7 @@ class ContainerImpl implements Container {
|
||||
Inject findInject(Annotation[] annotations) {
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation.annotationType() == Inject.class) {
|
||||
return Inject.class.cast(annotation);
|
||||
return (Inject) annotation;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
@@ -283,7 +284,7 @@ class ContainerImpl implements Container {
|
||||
method.setAccessible(true);
|
||||
} catch (AccessControlException e) {
|
||||
throw new DependencyException("Security manager in use, could not access method: "
|
||||
+ name + "(" + method.getName() + ")", e);
|
||||
+ name + "(" + method.getName() + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -292,7 +293,7 @@ class ContainerImpl implements Container {
|
||||
throw new DependencyException(method + " has no parameters to inject.");
|
||||
}
|
||||
parameterInjectors = container.getParametersInjectors(
|
||||
method, method.getParameterAnnotations(), parameterTypes, name);
|
||||
method, method.getParameterAnnotations(), parameterTypes, name);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -305,14 +306,12 @@ class ContainerImpl implements Container {
|
||||
}
|
||||
}
|
||||
|
||||
Map<Class<?>, ConstructorInjector> constructors =
|
||||
new ReferenceCache<Class<?>, ConstructorInjector>() {
|
||||
@Override
|
||||
@SuppressWarnings("unchecked")
|
||||
protected ConstructorInjector<?> create(Class<?> implementation) {
|
||||
return new ConstructorInjector(ContainerImpl.this, implementation);
|
||||
}
|
||||
};
|
||||
Map<Class<?>, ConstructorInjector<?>> constructors = new ReferenceCache<Class<?>, ConstructorInjector<?>>() {
|
||||
@Override
|
||||
protected ConstructorInjector<?> create(Class<?> implementation) {
|
||||
return new ConstructorInjector<>(ContainerImpl.this, implementation);
|
||||
}
|
||||
};
|
||||
|
||||
static class ConstructorInjector<T> {
|
||||
|
||||
@@ -334,7 +333,7 @@ class ContainerImpl implements Container {
|
||||
constructor.setAccessible(true);
|
||||
} catch (AccessControlException e) {
|
||||
throw new DependencyException("Security manager in use, could not access constructor: "
|
||||
+ implementation.getName() + "(" + constructor.getName() + ")", e);
|
||||
+ implementation.getName() + "(" + constructor.getName() + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -359,14 +358,14 @@ class ContainerImpl implements Container {
|
||||
}
|
||||
|
||||
ParameterInjector<?>[] constructParameterInjector(
|
||||
Inject inject, ContainerImpl container, Constructor<T> constructor) throws MissingDependencyException {
|
||||
Inject inject, ContainerImpl container, Constructor<T> constructor) throws MissingDependencyException {
|
||||
return constructor.getParameterTypes().length == 0
|
||||
? null // default constructor.
|
||||
: container.getParametersInjectors(
|
||||
constructor,
|
||||
constructor.getParameterAnnotations(),
|
||||
constructor.getParameterTypes(),
|
||||
inject.value()
|
||||
? null // default constructor.
|
||||
: container.getParametersInjectors(
|
||||
constructor,
|
||||
constructor.getParameterAnnotations(),
|
||||
constructor.getParameterTypes(),
|
||||
inject.value()
|
||||
);
|
||||
}
|
||||
|
||||
@@ -378,7 +377,7 @@ class ContainerImpl implements Container {
|
||||
if (constructor.getAnnotation(Inject.class) != null) {
|
||||
if (found != null) {
|
||||
throw new DependencyException("More than one constructor annotated"
|
||||
+ " with @Inject found in " + implementation + ".");
|
||||
+ " with @Inject found in " + implementation + ".");
|
||||
}
|
||||
found = constructor;
|
||||
}
|
||||
@@ -466,7 +465,7 @@ class ContainerImpl implements Container {
|
||||
}
|
||||
}
|
||||
|
||||
private static Object[] getParameters(Member member, InternalContext context, ParameterInjector[] parameterInjectors) {
|
||||
private static Object[] getParameters(Member member, InternalContext context, ParameterInjector<?>[] parameterInjectors) {
|
||||
if (parameterInjectors == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -494,13 +493,12 @@ class ContainerImpl implements Container {
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> T getInstance(Class<T> type, String name, InternalContext context) {
|
||||
final ExternalContext<?> previous = context.getExternalContext();
|
||||
final Key<T> key = Key.newInstance(type, name);
|
||||
context.setExternalContext(ExternalContext.newInstance(null, key, this));
|
||||
try {
|
||||
final InternalFactory o = getFactory(key);
|
||||
final InternalFactory<? extends T> o = getFactory(key);
|
||||
if (o != null) {
|
||||
return getFactory(key).create(context);
|
||||
} else {
|
||||
@@ -517,39 +515,25 @@ class ContainerImpl implements Container {
|
||||
|
||||
@Override
|
||||
public void inject(final Object o) {
|
||||
callInContext(new ContextualCallable<Void>() {
|
||||
public Void call(InternalContext context) {
|
||||
inject(o, context);
|
||||
return null;
|
||||
}
|
||||
callInContext((ContextualCallable<Void>) context -> {
|
||||
inject(o, context);
|
||||
return null;
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T inject(final Class<T> implementation) {
|
||||
return callInContext(new ContextualCallable<T>() {
|
||||
public T call(InternalContext context) {
|
||||
return inject(implementation, context);
|
||||
}
|
||||
});
|
||||
return callInContext(context -> inject(implementation, context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getInstance(final Class<T> type, final String name) {
|
||||
return callInContext(new ContextualCallable<T>() {
|
||||
public T call(InternalContext context) {
|
||||
return getInstance(type, name, context);
|
||||
}
|
||||
});
|
||||
return callInContext(context -> getInstance(type, name, context));
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T getInstance(final Class<T> type) {
|
||||
return callInContext(new ContextualCallable<T>() {
|
||||
public T call(InternalContext context) {
|
||||
return getInstance(type, context);
|
||||
}
|
||||
});
|
||||
return callInContext(context -> getInstance(type, context));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -561,12 +545,7 @@ class ContainerImpl implements Container {
|
||||
return names;
|
||||
}
|
||||
|
||||
ThreadLocal<Object[]> localContext = new ThreadLocal<Object[]>() {
|
||||
@Override
|
||||
protected Object[] initialValue() {
|
||||
return new Object[1];
|
||||
}
|
||||
};
|
||||
ThreadLocal<Object[]> localContext = ThreadLocal.withInitial(() -> new Object[1]);
|
||||
|
||||
/**
|
||||
* Looks up thread local context. Creates (and removes) a new context if necessary.
|
||||
@@ -598,7 +577,7 @@ class ContainerImpl implements Container {
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
<T> ConstructorInjector<T> getConstructor(Class<T> implementation) {
|
||||
return constructors.get(implementation);
|
||||
return (ConstructorInjector<T>) constructors.get(implementation);
|
||||
}
|
||||
|
||||
final ThreadLocal<Object> localScopeStrategy = new ThreadLocal<>();
|
||||
|
||||
@@ -25,21 +25,31 @@ import com.opensymphony.xwork2.ActionInvocation;
|
||||
*/
|
||||
public abstract class AbstractInterceptor implements Interceptor {
|
||||
|
||||
private boolean disabled;
|
||||
|
||||
/**
|
||||
* Does nothing
|
||||
*/
|
||||
public void init() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Does nothing
|
||||
*/
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Override to handle interception
|
||||
*/
|
||||
public abstract String intercept(ActionInvocation invocation) throws Exception;
|
||||
|
||||
public void setDisabled(String disable) {
|
||||
this.disabled = Boolean.parseBoolean(disable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isDisabled(ActionInvocation invocation) {
|
||||
return this.disabled;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -219,4 +219,12 @@ public interface Interceptor extends Serializable {
|
||||
*/
|
||||
String intercept(ActionInvocation invocation) throws Exception;
|
||||
|
||||
/**
|
||||
* Allows to disable processing a given interceptor
|
||||
*
|
||||
* @param invocation current {@link ActionInvocation} to determine if the interceptor should be executed
|
||||
* @return true if the given interceptor should be skipped
|
||||
* @since 6.1.0
|
||||
*/
|
||||
boolean isDisabled(ActionInvocation invocation);
|
||||
}
|
||||
|
||||
@@ -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 com.opensymphony.xwork2.interceptor;
|
||||
|
||||
/**
|
||||
* This interface is implemented by actions that want to declare acceptable parameter value. 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 the action will accept the parameter with the given value.
|
||||
*
|
||||
* @param parameterValue the parameter value
|
||||
* @return <tt>true</tt> if accepted, <tt>false</tt> otherwise
|
||||
*/
|
||||
boolean acceptableParameterValue(String parameterValue);
|
||||
|
||||
}
|
||||
+166
-12
@@ -26,6 +26,7 @@ import com.opensymphony.xwork2.security.AcceptedPatternsChecker;
|
||||
import com.opensymphony.xwork2.security.ExcludedPatternsChecker;
|
||||
import com.opensymphony.xwork2.util.ClearableValueStack;
|
||||
import com.opensymphony.xwork2.util.MemberAccessValueStack;
|
||||
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;
|
||||
@@ -33,12 +34,15 @@ import org.apache.commons.lang3.BooleanUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.dispatcher.Parameter;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
import org.apache.struts2.dispatcher.Parameter;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.TreeMap;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
@@ -62,6 +66,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
private ValueStackFactory valueStackFactory;
|
||||
private ExcludedPatternsChecker excludedPatterns;
|
||||
private AcceptedPatternsChecker acceptedPatterns;
|
||||
private Set<Pattern> excludedValuePatterns = null;
|
||||
private Set<Pattern> acceptedValuePatterns = null;
|
||||
|
||||
@Inject
|
||||
public void setValueStackFactory(ValueStackFactory valueStackFactory) {
|
||||
@@ -183,8 +189,10 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
|
||||
for (Map.Entry<String, Parameter> entry : params.entrySet()) {
|
||||
String parameterName = entry.getKey();
|
||||
boolean isAcceptableParameter = isAcceptableParameter(parameterName, action);
|
||||
isAcceptableParameter &= isAcceptableParameterValue(entry.getValue(), action);
|
||||
|
||||
if (isAcceptableParameter(parameterName, action)) {
|
||||
if (isAcceptableParameter) {
|
||||
acceptableParameters.put(parameterName, entry.getValue());
|
||||
}
|
||||
}
|
||||
@@ -201,7 +209,7 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
ReflectionContextState.setReportingConversionErrors(context, true);
|
||||
|
||||
//keep locale from original context
|
||||
newStack.getActionContext().withLocale(stack.getActionContext().getLocale());
|
||||
newStack.getActionContext().withLocale(stack.getActionContext().getLocale()).withValueStack(stack);
|
||||
}
|
||||
|
||||
boolean memberAccessStack = newStack instanceof MemberAccessValueStack;
|
||||
@@ -237,8 +245,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
if (action instanceof TextProvider) {
|
||||
TextProvider tp = (TextProvider) action;
|
||||
developerNotification = tp.getText("devmode.notification",
|
||||
"Developer Notification:\n{0}",
|
||||
new String[]{developerNotification}
|
||||
"Developer Notification:\n{0}",
|
||||
new String[]{developerNotification}
|
||||
);
|
||||
}
|
||||
|
||||
@@ -264,6 +272,23 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
return acceptableName(name) && (parameterNameAware == null || parameterNameAware.acceptableParameterName(name));
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if parameter value can be accepted or thrown away
|
||||
*
|
||||
* @param param the parameter
|
||||
* @param action current action
|
||||
* @return true if parameter is accepted
|
||||
*/
|
||||
protected boolean isAcceptableParameterValue(Parameter param, Object action) {
|
||||
ParameterValueAware parameterValueAware = (action instanceof ParameterValueAware) ? (ParameterValueAware) action : null;
|
||||
boolean acceptableParamValue = (parameterValueAware == null || parameterValueAware.acceptableParameterValue(param.getValue()));
|
||||
if (hasParamValuesToExclude() || hasParamValuesToAccept()) {
|
||||
// Additional validations to process
|
||||
acceptableParamValue &= acceptableValue(param.getName(), param.getValue());
|
||||
}
|
||||
return acceptableParamValue;
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
@@ -291,6 +316,15 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
return logEntry.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the name passed is:
|
||||
* * Within the max length of a parameter name
|
||||
* * Is not excluded
|
||||
* * Is accepted
|
||||
*
|
||||
* @param name - Name to check
|
||||
* @return true if accepted
|
||||
*/
|
||||
protected boolean acceptableName(String name) {
|
||||
if (isIgnoredDMI(name)) {
|
||||
LOG.trace("DMI is enabled, ignoring DMI method: {}", name);
|
||||
@@ -311,14 +345,37 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates:
|
||||
* * Value is null/blank
|
||||
* * Value is not excluded
|
||||
* * Value is accepted
|
||||
*
|
||||
* @param name - Param name (for logging)
|
||||
* @param value - value to check
|
||||
* @return true if accepted
|
||||
*/
|
||||
protected boolean acceptableValue(String name, String value) {
|
||||
boolean accepted = (value == null || value.isEmpty() || (!isParamValueExcluded(value) && isParamValueAccepted(value)));
|
||||
if (!accepted) {
|
||||
String message = "Value [{}] of parameter [{}] was not accepted and will be dropped!";
|
||||
if (devMode) {
|
||||
LOG.warn(message, value, name);
|
||||
} else {
|
||||
LOG.debug(message, value, name);
|
||||
}
|
||||
}
|
||||
return accepted;
|
||||
}
|
||||
|
||||
protected boolean isWithinLengthLimit(String name) {
|
||||
boolean matchLength = name.length() <= paramNameMaxLength;
|
||||
if (!matchLength) {
|
||||
if (devMode) { // warn only when in devMode
|
||||
LOG.warn("Parameter [{}] is too long, allowed length is [{}]. Use Interceptor Parameter Overriding " +
|
||||
"to override the limit, see more at\n" +
|
||||
"https://struts.apache.org/core-developers/interceptors.html#interceptor-parameter-overriding",
|
||||
name, paramNameMaxLength);
|
||||
"to override the limit, see more at\n" +
|
||||
"https://struts.apache.org/core-developers/interceptors.html#interceptor-parameter-overriding",
|
||||
name, paramNameMaxLength);
|
||||
} else {
|
||||
LOG.warn("Parameter [{}] is too long, allowed length is [{}]", name, paramNameMaxLength);
|
||||
}
|
||||
@@ -332,8 +389,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
return true;
|
||||
} else if (devMode) { // warn only when in devMode
|
||||
LOG.warn("Parameter [{}] didn't match accepted pattern [{}]! See Accepted / Excluded patterns at\n" +
|
||||
"https://struts.apache.org/security/#accepted--excluded-patterns",
|
||||
paramName, result.getAcceptedPattern());
|
||||
"https://struts.apache.org/security/#accepted--excluded-patterns",
|
||||
paramName, result.getAcceptedPattern());
|
||||
} else {
|
||||
LOG.debug("Parameter [{}] didn't match accepted pattern [{}]!", paramName, result.getAcceptedPattern());
|
||||
}
|
||||
@@ -345,8 +402,8 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
if (result.isExcluded()) {
|
||||
if (devMode) { // warn only when in devMode
|
||||
LOG.warn("Parameter [{}] matches excluded pattern [{}]! See Accepted / Excluded patterns at\n" +
|
||||
"https://struts.apache.org/security/#accepted--excluded-patterns",
|
||||
paramName, result.getExcludedPattern());
|
||||
"https://struts.apache.org/security/#accepted--excluded-patterns",
|
||||
paramName, result.getExcludedPattern());
|
||||
} else {
|
||||
LOG.debug("Parameter [{}] matches excluded pattern [{}]!", paramName, result.getExcludedPattern());
|
||||
}
|
||||
@@ -355,6 +412,54 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isParamValueExcluded(String value) {
|
||||
if (!hasParamValuesToExclude()) {
|
||||
LOG.debug("'excludedValuePatterns' not defined so anything is allowed");
|
||||
return false;
|
||||
}
|
||||
for (Pattern excludedValuePattern : excludedValuePatterns) {
|
||||
if (excludedValuePattern.matcher(value).matches()) {
|
||||
if (devMode) {
|
||||
LOG.warn("Parameter value [{}] matches excluded pattern [{}]! See Accepting/Excluding parameter values at\n" +
|
||||
"https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values",
|
||||
value, excludedValuePatterns);
|
||||
} else {
|
||||
LOG.debug("Parameter value [{}] matches excluded pattern [{}]", value, excludedValuePattern);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected boolean isParamValueAccepted(String value) {
|
||||
if (!hasParamValuesToAccept()) {
|
||||
LOG.debug("'acceptedValuePatterns' not defined so anything is allowed");
|
||||
return true;
|
||||
}
|
||||
for (Pattern acceptedValuePattern : acceptedValuePatterns) {
|
||||
if (acceptedValuePattern.matcher(value).matches()) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (devMode) {
|
||||
LOG.warn("Parameter value [{}] didn't match accepted pattern [{}]! See Accepting/Excluding parameter values at\n" +
|
||||
"https://struts.apache.org/core-developers/parameters-interceptor#excluding-parameter-values",
|
||||
value, acceptedValuePatterns);
|
||||
} else {
|
||||
LOG.debug("Parameter value [{}] was not accepted!", value);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean hasParamValuesToExclude() {
|
||||
return excludedValuePatterns != null && excludedValuePatterns.size() > 0;
|
||||
}
|
||||
|
||||
private boolean hasParamValuesToAccept() {
|
||||
return acceptedValuePatterns != null && acceptedValuePatterns.size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether to order the parameters or not
|
||||
*
|
||||
@@ -397,4 +502,53 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
excludedPatterns.setExcludedPatterns(commaDelim);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a comma-delimited list of regular expressions to match
|
||||
* values of parameters that should be accepted and included in the parameter map.
|
||||
*
|
||||
* @param commaDelimitedPatterns A comma-delimited set of regular expressions
|
||||
*/
|
||||
public void setAcceptedValuePatterns(String commaDelimitedPatterns) {
|
||||
Set<String> patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
|
||||
if (acceptedValuePatterns == null) {
|
||||
// Limit unwanted log entries (for 1st call, acceptedValuePatterns null)
|
||||
LOG.debug("Sets accepted value patterns to [{}], note this may impact the safety of your application!", patterns);
|
||||
} else {
|
||||
LOG.warn("Replacing accepted patterns [{}] with [{}], be aware that this may impact safety of your application!",
|
||||
acceptedValuePatterns, patterns);
|
||||
}
|
||||
acceptedValuePatterns = new HashSet<>(patterns.size());
|
||||
try {
|
||||
for (String pattern : patterns) {
|
||||
acceptedValuePatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
} finally {
|
||||
acceptedValuePatterns = Collections.unmodifiableSet(acceptedValuePatterns);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a comma-delimited list of regular expressions to match
|
||||
* values of parameters that should be removed from the parameter map.
|
||||
*
|
||||
* @param commaDelimitedPatterns A comma-delimited set of regular expressions
|
||||
*/
|
||||
public void setExcludedValuePatterns(String commaDelimitedPatterns) {
|
||||
Set<String> patterns = TextParseUtil.commaDelimitedStringToSet(commaDelimitedPatterns);
|
||||
if (excludedValuePatterns == null) {
|
||||
// Limit unwanted log entries (for 1st call, excludedValuePatterns null)
|
||||
LOG.debug("Setting excluded value patterns to [{}]", patterns);
|
||||
} else {
|
||||
LOG.warn("Replacing excluded value patterns [{}] with [{}], be aware that this may impact safety of your application!",
|
||||
excludedValuePatterns, patterns);
|
||||
}
|
||||
excludedValuePatterns = new HashSet<>(patterns.size());
|
||||
try {
|
||||
for (String pattern : patterns) {
|
||||
excludedValuePatterns.add(Pattern.compile(pattern, Pattern.CASE_INSENSITIVE));
|
||||
}
|
||||
} finally {
|
||||
excludedValuePatterns = Collections.unmodifiableSet(excludedValuePatterns);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,7 +73,6 @@ public class OgnlUtil {
|
||||
|
||||
private Container container;
|
||||
private boolean allowStaticFieldAccess = true;
|
||||
private boolean allowStaticMethodAccess;
|
||||
private boolean disallowProxyMemberAccess;
|
||||
|
||||
/**
|
||||
@@ -83,7 +82,9 @@ public class OgnlUtil {
|
||||
*/
|
||||
@Deprecated
|
||||
public OgnlUtil() {
|
||||
this(null, null); // Instantiate default Expression and BeanInfo caches (null factories)
|
||||
// Instantiate default Expression and BeanInfo caches (factories must be non-null).
|
||||
this(new DefaultOgnlExpressionCacheFactory<String, Object>(),
|
||||
new DefaultOgnlBeanInfoCacheFactory<Class<?>, BeanInfo>());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -97,10 +98,17 @@ public class OgnlUtil {
|
||||
* @param ognlExpressionCacheFactory factory for Expression cache instance. If null, it uses a default
|
||||
* @param ognlBeanInfoCacheFactory factory for BeanInfo cache instance. If null, it uses a default
|
||||
*/
|
||||
@Inject
|
||||
public OgnlUtil(
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_EXPRESSION_CACHE_FACTORY, required = false) ExpressionCacheFactory<String, Object> ognlExpressionCacheFactory,
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_BEANINFO_CACHE_FACTORY, required = false) BeanInfoCacheFactory<Class<?>, BeanInfo> ognlBeanInfoCacheFactory
|
||||
@Inject ExpressionCacheFactory<String, Object> ognlExpressionCacheFactory,
|
||||
@Inject BeanInfoCacheFactory<Class<?>, BeanInfo> ognlBeanInfoCacheFactory
|
||||
) {
|
||||
if (ognlExpressionCacheFactory == null) {
|
||||
throw new IllegalArgumentException("ExpressionCacheFactory parameter cannot be null");
|
||||
}
|
||||
if (ognlBeanInfoCacheFactory == null) {
|
||||
throw new IllegalArgumentException("BeanInfoCacheFactory parameter cannot be null");
|
||||
}
|
||||
excludedClasses = Collections.unmodifiableSet(new HashSet<>());
|
||||
excludedPackageNamePatterns = Collections.unmodifiableSet(new HashSet<>());
|
||||
excludedPackageNames = Collections.unmodifiableSet(new HashSet<>());
|
||||
@@ -109,11 +117,8 @@ public class OgnlUtil {
|
||||
devModeExcludedPackageNamePatterns = Collections.unmodifiableSet(new HashSet<>());
|
||||
devModeExcludedPackageNames = Collections.unmodifiableSet(new HashSet<>());
|
||||
|
||||
OgnlCacheFactory<String, Object> ognlExpressionCacheFactory1 = (ognlExpressionCacheFactory != null ? ognlExpressionCacheFactory : new DefaultOgnlExpressionCacheFactory<>());
|
||||
OgnlCacheFactory<Class<?>, BeanInfo> ognlBeanInfoCacheFactory1 = (ognlBeanInfoCacheFactory != null ? ognlBeanInfoCacheFactory : new DefaultOgnlBeanInfoCacheFactory<>());
|
||||
|
||||
this.expressionCache = ognlExpressionCacheFactory1.buildOgnlCache();
|
||||
this.beanInfoCache = ognlBeanInfoCacheFactory1.buildOgnlCache();
|
||||
this.expressionCache = ognlExpressionCacheFactory.buildOgnlCache();
|
||||
this.beanInfoCache = ognlBeanInfoCacheFactory.buildOgnlCache();
|
||||
}
|
||||
|
||||
@Inject
|
||||
@@ -250,11 +255,6 @@ public class OgnlUtil {
|
||||
this.allowStaticFieldAccess = BooleanUtils.toBoolean(allowStaticFieldAccess);
|
||||
}
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_ALLOW_STATIC_METHOD_ACCESS, required = false)
|
||||
protected void setAllowStaticMethodAccess(String allowStaticMethodAccess) {
|
||||
this.allowStaticMethodAccess = BooleanUtils.toBoolean(allowStaticMethodAccess);
|
||||
}
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_DISALLOW_PROXY_MEMBER_ACCESS, required = false)
|
||||
protected void setDisallowProxyMemberAccess(String disallowProxyMemberAccess) {
|
||||
this.disallowProxyMemberAccess = BooleanUtils.toBoolean(disallowProxyMemberAccess);
|
||||
@@ -268,10 +268,10 @@ public class OgnlUtil {
|
||||
try {
|
||||
if (maxLength == null || maxLength.isEmpty()) {
|
||||
Ognl.applyExpressionMaxLength(null);
|
||||
LOG.info("OGNL Expression Max Length disabled.");
|
||||
LOG.warn("OGNL Expression Max Length disabled.");
|
||||
} else {
|
||||
Ognl.applyExpressionMaxLength(Integer.parseInt(maxLength));
|
||||
LOG.info("OGNL Expression Max Length enabled with {}.", maxLength);
|
||||
LOG.debug("OGNL Expression Max Length enabled with {}.", maxLength);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
LOG.error("Unable to set OGNL Expression Max Length {}.", maxLength); // Help configuration debugging.
|
||||
@@ -836,7 +836,7 @@ public class OgnlUtil {
|
||||
resolver = container.getInstance(CompoundRootAccessor.class);
|
||||
}
|
||||
|
||||
SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticMethodAccess, allowStaticFieldAccess);
|
||||
SecurityMemberAccess memberAccess = new SecurityMemberAccess(allowStaticFieldAccess);
|
||||
memberAccess.setDisallowProxyMemberAccess(disallowProxyMemberAccess);
|
||||
|
||||
if (devMode) {
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user