mirror of
https://github.com/apache/struts.git
synced 2026-08-07 23:57:03 +00:00
Compare commits
199 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| daa62ed42a | |||
| 86b9438c95 | |||
| 6aa62bed80 | |||
| 3607a431d8 | |||
| 56e16de9c1 | |||
| 25168e8db3 | |||
| 93153bee52 | |||
| c213d2fa6c | |||
| 23cb69662f | |||
| b9b7b14444 | |||
| 198a388fb4 | |||
| 8014b1bdce | |||
| d2f09a8c54 | |||
| fe040f475b | |||
| a80c3217bc | |||
| 3f39accc97 | |||
| 2bb92b0afc | |||
| c3d9bd313b | |||
| 71c6669067 | |||
| f43d64ab54 | |||
| 6d189742cd | |||
| 254df5ef9b | |||
| 6103113e9b | |||
| 8d6b944946 | |||
| a83155009c | |||
| f41ffc2421 | |||
| 33113a90c6 | |||
| 7b0ae6e96a | |||
| d4e3b19c9f | |||
| 7dafbb773f | |||
| 5ebf37efba | |||
| f8166d5e8b | |||
| 352fdb5300 | |||
| 9215250aad | |||
| 030c7e0193 | |||
| 7c795d7366 | |||
| bbdbe79929 | |||
| f4d486dbd3 | |||
| c502db56c1 | |||
| 38615eb398 | |||
| 6e1aa0784b | |||
| 9fa90cb8b4 | |||
| 2291033724 | |||
| 0da2e1bd1b | |||
| 7b94ab8e8d | |||
| 0d5093796d | |||
| 75c4c5ee25 | |||
| b90c0c8e60 | |||
| f207ed6978 | |||
| 268854f353 | |||
| 6c24b2e73c | |||
| d47688da3e | |||
| 08cd7213d4 | |||
| 7ebff0ee12 | |||
| ae2f937761 | |||
| 2e82cb684c | |||
| 6e131b75f3 | |||
| c8397a1188 | |||
| aebc654a59 | |||
| 4bc9f8f62d | |||
| 157eacdecd | |||
| 768f3973c2 | |||
| 10e69d7d93 | |||
| 718fa71af1 | |||
| fbaccd65ec | |||
| a3ee86862f | |||
| 9407fe5e30 | |||
| 5ecfccb0ed | |||
| f6bba24d44 | |||
| 4f46d2abb2 | |||
| 5397257cfb | |||
| ad49562c48 | |||
| dbedc4fae4 | |||
| 9fb18e8c0e | |||
| e135288df6 | |||
| 6199a40267 | |||
| 7ea81313d0 | |||
| f7a7d62a87 | |||
| 96683b99fc | |||
| bccea9737c | |||
| 7ba66cfd4c | |||
| 2cf1f83121 | |||
| f537d7b33b | |||
| 3ea1503324 | |||
| 502d7f3987 | |||
| 1f1c996eb1 | |||
| 3a08768f32 | |||
| b8c94a58b9 | |||
| b2c5190d52 | |||
| 04fcefa44b | |||
| e40a8e540b | |||
| dcf5d45fde | |||
| dea5b76acc | |||
| 73df90c49f | |||
| 9e5c40482e | |||
| 68d84d684d | |||
| 18724a34cb | |||
| 4db454df70 | |||
| b57ec7454a | |||
| 3d0cd93746 | |||
| 32683d3acd | |||
| 6070c4ff6d | |||
| abef0ef66f | |||
| 708019a721 | |||
| be385243cd | |||
| 92c1e7e8ff | |||
| b0666945bb | |||
| 568ea0598d | |||
| bead99cf95 | |||
| 0a0c3293ed | |||
| f2ff3a81d2 | |||
| 0b8fcdf609 | |||
| bc7ae89de3 | |||
| a5ae3c599b | |||
| a4ee229d43 | |||
| 60eddc6f17 | |||
| 78e853bcb3 | |||
| b43e67584c | |||
| 828b457ad6 | |||
| 0f08615c62 | |||
| 48dbfd8104 | |||
| f36ac2fcc0 | |||
| 122ab67bc1 | |||
| 108a676ee0 | |||
| 663365f156 | |||
| 2fd890506d | |||
| c5a87c85b8 | |||
| f7f3deedc8 | |||
| 295150b5e9 | |||
| 1fe337bb3d | |||
| 8d395ee27c | |||
| 8ced5d0f1f | |||
| b69f71aa2e | |||
| a4b404075c | |||
| 0d72932171 | |||
| 8f5e79d987 | |||
| 37371b3684 | |||
| cc68365a5f | |||
| 3fb3be2532 | |||
| e839817c48 | |||
| dad9f86de4 | |||
| 51ef883a72 | |||
| d733e103ba | |||
| 0a23cd4ec5 | |||
| 59d65a0aa7 | |||
| 2a7a22b206 | |||
| 561b08386a | |||
| 8378fbbd22 | |||
| 886cbda5cd | |||
| 9cbdb09169 | |||
| 6736da66a5 | |||
| d24822fb69 | |||
| 7dc0031e33 | |||
| 5476f03918 | |||
| 5d9bed1745 | |||
| 6a5c87319d | |||
| e654941b34 | |||
| e8a2fb1497 | |||
| 5a5f88205d | |||
| c760241930 | |||
| bc3301bb3e | |||
| 423360d377 | |||
| 3b6d7cfe82 | |||
| 873d150890 | |||
| 5030b89b33 | |||
| d0e828d5a5 | |||
| f0efd27bb7 | |||
| 71d6d3fade | |||
| 8e7df5a712 | |||
| 492ab02d97 | |||
| 54bf39cfcd | |||
| 4c1cbed577 | |||
| 16241f95a6 | |||
| f54ce89923 | |||
| 7140edf5e5 | |||
| 9efd7fcfd9 | |||
| 92cea867a3 | |||
| 2c54264bcc | |||
| 6f47a90767 | |||
| fa6a04576e | |||
| 43d1be3774 | |||
| 36d82cbc7f | |||
| 2c1ffa7e73 | |||
| 5a2759896f | |||
| cf1150f58c | |||
| 2019385915 | |||
| e07b7eb7d2 | |||
| dae35dfd9c | |||
| 9067fdc945 | |||
| 66b2491338 | |||
| ac1d6b48b8 | |||
| 9a22985c1f | |||
| 565b8f8642 | |||
| 61c03b374d | |||
| e05d71ba32 | |||
| bdc01ffb85 | |||
| 06030a440c | |||
| 09b43b1838 | |||
| 373988eb4a |
+4
-4
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.1.2-SNAPSHOT</version>
|
||||
<version>2.1.3</version>
|
||||
</parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-blank</artifactId>
|
||||
@@ -34,9 +34,9 @@
|
||||
<name>Blank Webapp</name>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/blank/</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/apps/blank/</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/apps/blank/</url>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/blank</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/blank</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/apps/blank</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -10,6 +10,18 @@
|
||||
|
||||
<include file="example.xml"/>
|
||||
|
||||
|
||||
|
||||
<package name="default" namespace="/" extends="struts-default">
|
||||
<default-action-ref name="index" />
|
||||
<action name="index">
|
||||
<result type="redirectAction">
|
||||
<param name="actionName">HelloWorld</param>
|
||||
<param name="namespace">/example</param>
|
||||
</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
<!-- Add packages here -->
|
||||
|
||||
</struts>
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
<filter>
|
||||
<filter-name>struts2</filter-name>
|
||||
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
|
||||
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
|
||||
@@ -44,7 +44,7 @@ public class ConfigTest extends StrutsTestCase {
|
||||
ActionSupport.INPUT.equals(result));
|
||||
}
|
||||
|
||||
protected Map assertFieldErrors(ActionSupport action) throws Exception {
|
||||
protected Map<String, List<String>> assertFieldErrors(ActionSupport action) throws Exception {
|
||||
assertTrue(action.hasFieldErrors());
|
||||
return action.getFieldErrors();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.1.2-SNAPSHOT</version>
|
||||
<version>2.1.3</version>
|
||||
</parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-mailreader</artifactId>
|
||||
@@ -34,9 +34,9 @@
|
||||
<name>Starter Webapp</name>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/mailreader/</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/apps/mailreader/</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/apps/mailreader/</url>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/mailreader</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/mailreader</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/apps/mailreader</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
<filter>
|
||||
<filter-name>Struts2</filter-name>
|
||||
<filter-class>
|
||||
org.apache.struts2.dispatcher.FilterDispatcher
|
||||
org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
|
||||
</filter-class>
|
||||
</filter>
|
||||
|
||||
|
||||
+5
-21
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.1.2-SNAPSHOT</version>
|
||||
<version>2.1.3</version>
|
||||
</parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
@@ -41,9 +41,9 @@
|
||||
</modules>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/apps/</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/apps/</url>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/apps</url>
|
||||
</scm>
|
||||
|
||||
<distributionManagement>
|
||||
@@ -169,22 +169,6 @@
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.codehaus.cargo</groupId>
|
||||
<artifactId>cargo-maven2-plugin</artifactId>
|
||||
<version>0.3.1</version>
|
||||
<configuration>
|
||||
<container>
|
||||
<containerId>tomcat5x</containerId>
|
||||
<home>${cargo.tomcat5x.home}</home>
|
||||
<log>${project.build.directory}/tomcat5x.log</log>
|
||||
<output>${project.build.directory}/tomcat5x.out</output>
|
||||
</container>
|
||||
<configuration>
|
||||
<home>${project.build.directory}/tomcat5x</home>
|
||||
</configuration>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!-- Include source code under WEB-INF/src/java -->
|
||||
<plugin>
|
||||
<artifactId>maven-antrun-plugin</artifactId>
|
||||
@@ -247,4 +231,4 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.1.2-SNAPSHOT</version>
|
||||
<version>2.1.3</version>
|
||||
</parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-portlet</artifactId>
|
||||
@@ -34,9 +34,9 @@
|
||||
<name>Portlet Webapp</name>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/portlet/</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/apps/portlet/</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/apps/portlet/</url>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/portlet</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/portlet</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/apps/portlet</url>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
|
||||
@@ -26,22 +26,27 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.1.2-SNAPSHOT</version>
|
||||
<version>2.1.3</version>
|
||||
</parent>
|
||||
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-rest-showcase</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>2.1.2-SNAPSHOT</version>
|
||||
<version>2.1.3</version>
|
||||
<name>Struts 2 Rest Showcase Example</name>
|
||||
<description>Struts 2 Rest Showcase Example</description>
|
||||
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-rest-plugin</artifactId>
|
||||
<version>${pom.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-convention-plugin</artifactId>
|
||||
<version>${pom.version}</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
@@ -49,9 +54,36 @@
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.jwebunit</groupId>
|
||||
<artifactId>jwebunit-core</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-httpclient</groupId>
|
||||
<artifactId>commons-httpclient</artifactId>
|
||||
<version>3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.jwebunit</groupId>
|
||||
<artifactId>jwebunit-htmlunit-plugin</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>xom</groupId>
|
||||
<artifactId>xom</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
<build>
|
||||
<finalName>struts2-rest-showcase</finalName>
|
||||
<plugins>
|
||||
@@ -70,6 +102,43 @@
|
||||
<scanIntervalSeconds>10</scanIntervalSeconds>
|
||||
</configuration>
|
||||
</plugin>
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.twdata.maven</groupId>
|
||||
<artifactId>maven-itblast-plugin</artifactId>
|
||||
<version>0.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>execute</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<containers>tomcat5x</containers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>it/**</exclude>
|
||||
<exclude>**/*$*</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
|
||||
<!--
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>twdata-m2-repository</id>
|
||||
<name>twdata.org Maven Repository</name>
|
||||
<url>http://twdata-m2-repository.googlecode.com/svn/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
-->
|
||||
</project>
|
||||
|
||||
+7
-3
@@ -2,18 +2,22 @@ package org.apache.struts2.rest.example;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.struts2.config.Result;
|
||||
import org.apache.struts2.config.Results;
|
||||
import org.apache.struts2.dispatcher.ServletActionRedirectResult;
|
||||
import org.apache.struts2.rest.DefaultHttpHeaders;
|
||||
import org.apache.struts2.rest.HttpHeaders;
|
||||
import org.apache.struts2.convention.annotation.Results;
|
||||
import org.apache.struts2.convention.annotation.Result;
|
||||
import org.apache.struts2.convention.annotation.ParentPackage;
|
||||
import org.apache.struts2.convention.annotation.Namespaces;
|
||||
import org.apache.struts2.convention.annotation.Namespace;
|
||||
import org.apache.struts2.convention.annotation.InterceptorRef;
|
||||
|
||||
import com.opensymphony.xwork2.ModelDriven;
|
||||
import com.opensymphony.xwork2.Validateable;
|
||||
import com.opensymphony.xwork2.ValidationAwareSupport;
|
||||
|
||||
@Results({
|
||||
@Result(name="success", type=ServletActionRedirectResult.class, value="orders")
|
||||
@Result(name="success", type="redirectAction", params = {"actionName" , "orders"})
|
||||
})
|
||||
public class OrdersController extends ValidationAwareSupport implements ModelDriven<Object>, Validateable{
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
/*
|
||||
* $Id: struts-plugin.xml 722219 2008-12-01 20:41:26Z musachy $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT 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.0//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.0.dtd">
|
||||
|
||||
<struts>
|
||||
<!-- Overwrite Convention -->
|
||||
<constant name="struts.convention.action.suffix" value="Controller"/>
|
||||
<constant name="struts.convention.action.mapAllMatches" value="true"/>
|
||||
<constant name="struts.convention.default.parent.package" value="rest-default"/>
|
||||
|
||||
<constant name="struts.convention.package.locators" value="example"/>
|
||||
</struts>
|
||||
@@ -12,11 +12,7 @@
|
||||
<!-- START SNIPPET: filter -->
|
||||
<filter>
|
||||
<filter-name>action2</filter-name>
|
||||
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
|
||||
<init-param>
|
||||
<param-name>actionPackages</param-name>
|
||||
<param-value>org.apache.struts2.rest.example</param-value>
|
||||
</init-param>
|
||||
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter</filter-class>
|
||||
</filter>
|
||||
<!-- END SNIPPET: filter -->
|
||||
|
||||
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
package it.org.apache.struts2.rest.example;
|
||||
|
||||
import net.sourceforge.jwebunit.junit.WebTestCase;
|
||||
|
||||
public class GetOrdersTest extends WebTestCase {
|
||||
|
||||
public void setUp() throws Exception {
|
||||
getTestContext().setBaseUrl(ParameterUtils.getBaseUrl());
|
||||
}
|
||||
|
||||
|
||||
public void testGetOrders() {
|
||||
beginAt("/orders/3");
|
||||
assertTextPresent("Bob");
|
||||
assertTextNotPresent("Sarah");
|
||||
}
|
||||
|
||||
public void testGetOrdersInHtml() {
|
||||
beginAt("/orders/3.xhtml");
|
||||
assertTextPresent("Bob");
|
||||
}
|
||||
|
||||
public void testGetOrdersInXml() {
|
||||
beginAt("/orders/3.xml");
|
||||
assertTextPresent("<clientName>Bob");
|
||||
}
|
||||
|
||||
public void testGetOrdersInJson() {
|
||||
beginAt("/orders/3.json");
|
||||
assertTextPresent("\"clientName\":\"Bob\"");
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
package it.org.apache.struts2.rest.example;
|
||||
|
||||
import net.sourceforge.jwebunit.junit.WebTestCase;
|
||||
|
||||
public class ListOrdersTest extends WebTestCase {
|
||||
|
||||
public void setUp() throws Exception {
|
||||
getTestContext().setBaseUrl(ParameterUtils.getBaseUrl());
|
||||
}
|
||||
|
||||
|
||||
public void testListOrders() {
|
||||
beginAt("/orders");
|
||||
assertTextPresent("Bob");
|
||||
assertTextPresent("Sarah");
|
||||
assertTextPresent("Jim");
|
||||
}
|
||||
|
||||
public void testListOrdersInHtml() {
|
||||
beginAt("/orders.xhtml");
|
||||
assertTextPresent("Bob");
|
||||
assertTextPresent("Sarah");
|
||||
assertTextPresent("Jim");
|
||||
}
|
||||
|
||||
public void testListOrdersInXml() {
|
||||
beginAt("/orders.xml");
|
||||
assertTextPresent("<clientName>Bob");
|
||||
assertTextPresent("<clientName>Sarah");
|
||||
assertTextPresent("<clientName>Jim");
|
||||
}
|
||||
|
||||
public void testListOrdersInJson() {
|
||||
beginAt("/orders.json");
|
||||
assertTextPresent("\"clientName\":\"Bob\"");
|
||||
assertTextPresent("\"clientName\":\"Sarah\"");
|
||||
assertTextPresent("\"clientName\":\"Jim\"");
|
||||
}
|
||||
}
|
||||
+12
@@ -0,0 +1,12 @@
|
||||
package it.org.apache.struts2.rest.example;
|
||||
|
||||
public class ParameterUtils {
|
||||
|
||||
public static String getBaseUrl() {
|
||||
String port = System.getProperty("http.port");
|
||||
if (port == null) {
|
||||
port = "8080";
|
||||
}
|
||||
return "http://localhost:"+port+"/struts2-rest-showcase";
|
||||
}
|
||||
}
|
||||
+121
@@ -0,0 +1,121 @@
|
||||
package it.org.apache.struts2.rest.example;
|
||||
|
||||
import net.sourceforge.jwebunit.junit.WebTestCase;
|
||||
import org.apache.commons.httpclient.HttpClient;
|
||||
import org.apache.commons.httpclient.methods.PostMethod;
|
||||
import org.apache.commons.httpclient.methods.StringRequestEntity;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.gargoylesoftware.htmlunit.FailingHttpStatusCodeException;
|
||||
|
||||
public class PostOrderTest extends WebTestCase {
|
||||
|
||||
public void setUp() throws Exception {
|
||||
getTestContext().setBaseUrl(ParameterUtils.getBaseUrl());
|
||||
}
|
||||
|
||||
|
||||
public void testPostOrder() {
|
||||
beginAt("/orders/new");
|
||||
setWorkingForm(0);
|
||||
setTextField("clientName", "Test1");
|
||||
setTextField("amount", "321");
|
||||
submit();
|
||||
assertTextPresent("Test1");
|
||||
assertLinkNotPresentWithText("Back to Orders");
|
||||
}
|
||||
|
||||
public void testPostOrderWithErrors() {
|
||||
beginAt("/orders/new");
|
||||
setWorkingForm(0);
|
||||
setTextField("amount", "321");
|
||||
try {
|
||||
submit();
|
||||
} catch (FailingHttpStatusCodeException ex) {
|
||||
// ignore;
|
||||
}
|
||||
assertTextPresent("client name is empty");
|
||||
assertTextFieldEquals("amount", "321");
|
||||
}
|
||||
|
||||
public void testPostOrderInHtml() {
|
||||
beginAt("/orders/new.xhtml");
|
||||
setWorkingForm(0);
|
||||
setTextField("clientName", "Test2");
|
||||
setTextField("amount", "321");
|
||||
try {
|
||||
submit();
|
||||
} catch (FailingHttpStatusCodeException ex) {
|
||||
// ignore;
|
||||
}
|
||||
assertTextPresent("Test2");
|
||||
assertLinkNotPresentWithText("Back to Orders");
|
||||
}
|
||||
|
||||
public void testPostOrderInXml() throws IOException {
|
||||
HttpClient client = new HttpClient();
|
||||
PostMethod method = null;
|
||||
try {
|
||||
method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.xml");
|
||||
method.setRequestEntity(new StringRequestEntity("<org.apache.struts2.rest.example.Order>\n" +
|
||||
"<clientName>Test3</clientName>\n" +
|
||||
"<amount>3342</amount>\n" +
|
||||
"</org.apache.struts2.rest.example.Order>"));
|
||||
client.executeMethod(method);
|
||||
assertEquals(201, method.getStatusCode());
|
||||
assertTrue(method.getResponseHeader("Location").getValue().startsWith(ParameterUtils.getBaseUrl()+"/orders/"));
|
||||
} finally {
|
||||
method.releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
public void testPostOrderInXmlWithBadData() throws IOException {
|
||||
HttpClient client = new HttpClient();
|
||||
PostMethod method = null;
|
||||
try {
|
||||
method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.xml");
|
||||
method.setRequestEntity(new StringRequestEntity("<org.apache.struts2.rest.example.Order>\n" +
|
||||
"<amount>3342</amount>\n" +
|
||||
"</org.apache.struts2.rest.example.Order>"));
|
||||
client.executeMethod(method);
|
||||
assertEquals(400, method.getStatusCode());
|
||||
String response = method.getResponseBodyAsString();
|
||||
assertTrue(response.contains("<string>The client name is empty"));
|
||||
assertNull(method.getResponseHeader("Location"));
|
||||
} finally {
|
||||
method.releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
public void testPostOrderInJson() throws IOException {
|
||||
HttpClient client = new HttpClient();
|
||||
PostMethod method = null;
|
||||
try {
|
||||
method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.json");
|
||||
method.setRequestEntity(new StringRequestEntity("{\"amount\":33,\"clientName\":\"Test4\"}"));
|
||||
client.executeMethod(method);
|
||||
assertEquals(201, method.getStatusCode());
|
||||
assertTrue(method.getResponseHeader("Location").getValue().startsWith(ParameterUtils.getBaseUrl()+"/orders/"));
|
||||
} finally {
|
||||
method.releaseConnection();
|
||||
}
|
||||
}
|
||||
|
||||
public void testPostOrderInJsonWithBadData() throws IOException {
|
||||
HttpClient client = new HttpClient();
|
||||
PostMethod method = null;
|
||||
try {
|
||||
method = new PostMethod(ParameterUtils.getBaseUrl()+"/orders.json");
|
||||
method.setRequestEntity(new StringRequestEntity("{\"amount\":33}"));
|
||||
client.executeMethod(method);
|
||||
String response = method.getResponseBodyAsString();
|
||||
assertEquals(400, method.getStatusCode());
|
||||
|
||||
assertEquals("{\"actionErrors\":[],\"fieldErrors\":{\"clientName\":[\"The client name is empty\"]}}", response);
|
||||
assertNull(method.getResponseHeader("Location"));
|
||||
} finally {
|
||||
method.releaseConnection();
|
||||
}
|
||||
}
|
||||
}
|
||||
+79
-16
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.1.2-SNAPSHOT</version>
|
||||
<version>2.1.3</version>
|
||||
</parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-showcase</artifactId>
|
||||
@@ -34,9 +34,9 @@
|
||||
<name>Showcase Webapp</name>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/apps/showcase/</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/apps/showcase/</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/apps/showcase/</url>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/showcase</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/apps/showcase</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/apps/showcase</url>
|
||||
</scm>
|
||||
|
||||
|
||||
@@ -181,6 +181,32 @@
|
||||
<version>1.1.1</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.jwebunit</groupId>
|
||||
<artifactId>jwebunit-core</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>commons-httpclient</groupId>
|
||||
<artifactId>commons-httpclient</artifactId>
|
||||
<version>3.1</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>net.sourceforge.jwebunit</groupId>
|
||||
<artifactId>jwebunit-htmlunit-plugin</artifactId>
|
||||
<version>1.4.1</version>
|
||||
<scope>test</scope>
|
||||
<exclusions>
|
||||
<exclusion>
|
||||
<groupId>xom</groupId>
|
||||
<artifactId>xom</artifactId>
|
||||
</exclusion>
|
||||
</exclusions>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
@@ -211,19 +237,56 @@
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</plugin>
|
||||
<!--
|
||||
<plugin>
|
||||
<groupId>org.twdata.maven</groupId>
|
||||
<artifactId>maven-itblast-plugin</artifactId>
|
||||
<version>0.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>integration-test</phase>
|
||||
<goals>
|
||||
<goal>execute</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<containers>tomcat5x</containers>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
-->
|
||||
<plugin>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<configuration>
|
||||
<excludes>
|
||||
<exclude>it/**</exclude>
|
||||
<exclude>**/*$*</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
<resources>
|
||||
<!-- Include resources under src/main/java in WEB-INF/classes -->
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.java</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
<resources>
|
||||
<!-- Include resources under src/main/java in WEB-INF/classes -->
|
||||
<resource>
|
||||
<directory>src/main/resources</directory>
|
||||
</resource>
|
||||
<resource>
|
||||
<directory>src/main/java</directory>
|
||||
<includes>
|
||||
<include>**/*.java</include>
|
||||
</includes>
|
||||
</resource>
|
||||
</resources>
|
||||
|
||||
</build>
|
||||
<!--
|
||||
<pluginRepositories>
|
||||
<pluginRepository>
|
||||
<id>twdata-m2-repository</id>
|
||||
<name>twdata.org Maven Repository</name>
|
||||
<url>http://twdata-m2-repository.googlecode.com/svn/</url>
|
||||
</pluginRepository>
|
||||
</pluginRepositories>
|
||||
-->
|
||||
</project>
|
||||
|
||||
+2
-2
@@ -18,6 +18,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// START SNIPPET: entire-file
|
||||
package org.apache.struts2.showcase.fileupload;
|
||||
|
||||
import java.io.File;
|
||||
@@ -44,7 +45,6 @@ public class MultipleFileUploadUsingArrayAction extends ActionSupport {
|
||||
public String[] getUploadContentType() { return this.uploadContentTypes; }
|
||||
public void setUploadContentType(String[] uploadContentType) { this.uploadContentTypes = uploadContentType; }
|
||||
|
||||
|
||||
public String upload() throws Exception {
|
||||
System.out.println("\n\n upload2");
|
||||
System.out.println("files:");
|
||||
@@ -62,5 +62,5 @@ public class MultipleFileUploadUsingArrayAction extends ActionSupport {
|
||||
System.out.println("\n\n");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
}
|
||||
// END SNIPPET: entire-file
|
||||
+2
-5
@@ -18,6 +18,7 @@
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
// START SNIPPET: entire-file
|
||||
package org.apache.struts2.showcase.fileupload;
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
@@ -57,9 +58,6 @@ public class MultipleFileUploadUsingListAction extends ActionSupport {
|
||||
this.uploadContentTypes = contentTypes;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
public String upload() throws Exception {
|
||||
|
||||
System.out.println("\n\n upload1");
|
||||
@@ -78,6 +76,5 @@ public class MultipleFileUploadUsingListAction extends ActionSupport {
|
||||
System.out.println("\n\n");
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
// END SNIPPET: entire-file
|
||||
@@ -3,7 +3,7 @@
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.0.dtd">
|
||||
|
||||
|
||||
<struts>
|
||||
<package name="ui-tags" extends="struts-default" namespace="/tags/ui">
|
||||
<action name="example" class="org.apache.struts2.showcase.UITagExample">
|
||||
@@ -40,26 +40,30 @@
|
||||
</action>
|
||||
|
||||
<!-- START SNIPPET: treeExampleDynamicXWorkXml -->
|
||||
|
||||
|
||||
<action name="showDynamicTreeAction" class="org.apache.struts2.showcase.ShowDynamicTreeAction">
|
||||
<result>/tags/ui/treeExampleDynamic.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
<!-- END SNIPPET: treeExampleDynamicXWorkXml -->
|
||||
|
||||
|
||||
<action name="showDynamicAjaxTreeAction">
|
||||
<result>/tags/ui/treeExampleAjaxDynamic.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
<action name="showComponentTagExampleCode">
|
||||
<result type="plainText">/tags/ui/componentTagExample.jsp</result>
|
||||
</action>
|
||||
|
||||
|
||||
<action name="actionTagExample">
|
||||
<result>/tags/ui/actionTagExampleCalled.jsp</result>
|
||||
<result name="input">/tags/ui/actionTagExampleCalling.jsp</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
|
||||
<!-- START SNIPPET: treeExampleXWorkXml -->
|
||||
|
||||
<package name="ui-tags-ajax" namespace="/tags/ui/ajax" extends="struts-default">
|
||||
|
||||
<package name="ui-tags-ajax" namespace="/tags/ui/ajax" extends="struts-default">
|
||||
<!-- Actions dealing with Tree Example -->
|
||||
<action name="staticTreeSelectAction">
|
||||
<result>/tags/ui/staticTreeSelect.jsp</result>
|
||||
@@ -68,6 +72,6 @@
|
||||
<result>/tags/ui/dynamicTreeSelect.jsp</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
|
||||
<!-- END SNIPPET: treeExampleXWorkXml -->
|
||||
</struts>
|
||||
|
||||
@@ -49,43 +49,43 @@
|
||||
</div><!-- end search -->
|
||||
|
||||
<hr/>
|
||||
<div style="clear: both;"></div>
|
||||
</div>
|
||||
</div><!-- end header -->
|
||||
|
||||
<div id="content" class="clearfix">
|
||||
|
||||
<decorator:body/>
|
||||
|
||||
<div id="nav">
|
||||
<div class="wrapper">
|
||||
<h2 class="accessibility">Navigation</h2>
|
||||
<ul class="clearfix">
|
||||
<li><a href="<s:url value="/showcase.jsp"/>">Home</a></li>
|
||||
<li><a href="<s:url value="/ajax/index.jsp"/>">Ajax</a></li>
|
||||
<li><a href="<s:url value="/chat/index.jsp"/>">Ajax Chat</a></li>
|
||||
<li><a href="<s:url action="actionChain1!input" namespace="/actionchaining" includeParams="none" />">Action Chaining</a></li>
|
||||
<li><a href="<s:url action="index" namespace="/config-browser" includeParams="none" />">Config Browser</a></li>
|
||||
<li><a href="<s:url value="/conversion/index.jsp"/>">Conversion</a></li>
|
||||
<li><a href="<s:url value="/empmanager/index.jsp"/>">CRUD</a></li>
|
||||
<li><a href="<s:url value="/wait/index.jsp"/>">Execute & Wait</a></li>
|
||||
<li><a href="<s:url value="/filedownload/index.jsp"/>">File Download</a></li>
|
||||
<li><a href="<s:url value="/fileupload" />">File Upload</a></li>
|
||||
<li><a href="<s:url value="/freemarker/index.jsp"/>">Freemarker</a>
|
||||
<li><a href="<s:url action="hangmanMenu" namespace="/hangman"/>">Hangman</a></li>
|
||||
<li><a href="<s:url value="/jsf/index.jsp"/>">JavaServer Faces</a></li>
|
||||
<li><a href="<s:url value="/person/index.jsp"/>">Person Manager</a></li>
|
||||
<li><a href="<s:url value="/tags/index.jsp"/>">Tags</a></li>
|
||||
<li><a href="<s:url value="/tiles/index.action" />">Tiles</a></li>
|
||||
<li><a href="<s:url value="/token/index.jsp"/>">Token</a></li>
|
||||
<li><a href="<s:url value="/validation/index.jsp"/>">Validation</a></li>
|
||||
<li><a href="<s:url value="/interactive/index.jsp"/>">Interactive Demo</a></li>
|
||||
<li class="last"><a href="<s:url value="/help.jsp"/>">Help</a></li>
|
||||
<li><a href="<s:url value="/showcase.jsp"/>">Home</a></li>
|
||||
<li><a href="<s:url value="/ajax/index.jsp"/>">Ajax</a></li>
|
||||
<li><a href="<s:url value="/chat/index.jsp"/>">Ajax Chat</a></li>
|
||||
<li><a href="<s:url action="actionChain1!input" namespace="/actionchaining" includeParams="none" />">Action Chaining</a></li>
|
||||
<li><a href="<s:url action="index" namespace="/config-browser" includeParams="none" />">Config Browser</a></li>
|
||||
<li><a href="<s:url value="/conversion/index.jsp"/>">Conversion</a></li>
|
||||
<li><a href="<s:url value="/empmanager/index.jsp"/>">CRUD</a></li>
|
||||
<li><a href="<s:url value="/wait/index.jsp"/>">Execute & Wait</a></li>
|
||||
<li><a href="<s:url value="/filedownload/index.jsp"/>">File Download</a></li>
|
||||
<li><a href="<s:url value="/fileupload/index.jsp" />">File Upload</a></li>
|
||||
<li><a href="<s:url value="/freemarker/index.jsp"/>">Freemarker</a>
|
||||
<li><a href="<s:url action="hangmanMenu" namespace="/hangman"/>">Hangman</a></li>
|
||||
<li><a href="<s:url value="/jsf/index.jsp"/>">JavaServer Faces</a></li>
|
||||
<li><a href="<s:url value="/tags/index.jsp"/>">Tags</a></li>
|
||||
<li><a href="<s:url value="/tiles/index.action" />">Tiles</a></li>
|
||||
<li><a href="<s:url value="/token/index.jsp"/>">Token</a></li>
|
||||
<li><a href="<s:url value="/validation/index.jsp"/>">Validation</a></li>
|
||||
<li><a href="<s:url value="/interactive/index.jsp"/>">Interactive Demo</a></li>
|
||||
<li><a href="<s:url value="/person/index.jsp"/>">Person Manager</a></li>
|
||||
<li class="last"><a href="<s:url value="/help.jsp"/>">Help</a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<hr/>
|
||||
|
||||
</div><!-- end nav -->
|
||||
|
||||
<decorator:body/>
|
||||
|
||||
</div><!-- end content -->
|
||||
|
||||
<div>
|
||||
|
||||
@@ -7,26 +7,26 @@
|
||||
<display-name>Struts Showcase Application</display-name>
|
||||
|
||||
<filter>
|
||||
<filter-name>struts-cleanup</filter-name>
|
||||
<filter-class>org.apache.struts2.dispatcher.ActionContextCleanUp</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter>
|
||||
<filter-name>struts</filter-name>
|
||||
<filter-class>org.apache.struts2.dispatcher.FilterDispatcher</filter-class>
|
||||
<filter-name>struts-prepare</filter-name>
|
||||
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter</filter-class>
|
||||
<init-param>
|
||||
<param-name>actionPackages</param-name>
|
||||
<param-value>org.apache.struts2.showcase.person</param-value>
|
||||
</init-param>
|
||||
</filter>
|
||||
|
||||
<filter>
|
||||
<filter-name>struts-execute</filter-name>
|
||||
<filter-class>org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter>
|
||||
<filter-name>sitemesh</filter-name>
|
||||
<filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
|
||||
</filter>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>struts-cleanup</filter-name>
|
||||
<filter-name>struts-prepare</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
@@ -36,7 +36,7 @@
|
||||
</filter-mapping>
|
||||
|
||||
<filter-mapping>
|
||||
<filter-name>struts</filter-name>
|
||||
<filter-name>struts-execute</filter-name>
|
||||
<url-pattern>/*</url-pattern>
|
||||
</filter-mapping>
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
position: relative;
|
||||
width: 98%;
|
||||
|
||||
margin: 5em auto 20px auto;
|
||||
margin: 5px auto 20px auto;
|
||||
padding: 0;
|
||||
|
||||
text-align: left;
|
||||
@@ -26,8 +26,6 @@
|
||||
display: none;
|
||||
}
|
||||
div#nav {
|
||||
position: absolute;
|
||||
top: -15px;
|
||||
left: 0;
|
||||
width: 100%;
|
||||
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
background: #818EBD;
|
||||
|
||||
text-align: left;
|
||||
height: 70px;
|
||||
}
|
||||
div#branding {
|
||||
float: left;
|
||||
|
||||
@@ -10,7 +10,6 @@
|
||||
/* end hide */
|
||||
}
|
||||
div#nav div.wrapper {
|
||||
position: absolute;
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
width: 100%;
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
<%@taglib prefix="s" uri="/struts-tags" %>
|
||||
This text is from the called class
|
||||
@@ -0,0 +1,14 @@
|
||||
<%@taglib prefix="s" uri="/struts-tags" %>
|
||||
|
||||
<html>
|
||||
<head>
|
||||
<title>Showcase - Tags - UI Tags - Action Tag</title>
|
||||
</head>
|
||||
<body>
|
||||
<b>Example 1:</b>
|
||||
This example calls an action and includes the output on the page
|
||||
<p id="example1" style="background-color:yellow;">
|
||||
<s:action namespace="/tags/ui" name="actionTagExample" executeResult="true"/>
|
||||
</p>
|
||||
</body>
|
||||
</html>
|
||||
@@ -16,8 +16,8 @@
|
||||
|
||||
|
||||
<s:form action="exampleSubmit" enctype="multipart/form-data" javascriptTooltip="true">
|
||||
<s:textfield
|
||||
label="Name"
|
||||
<s:textfield
|
||||
label="Name"
|
||||
name="name"
|
||||
tooltip="Enter your Name here"/>
|
||||
|
||||
@@ -25,13 +25,13 @@
|
||||
tooltip="Select Your Birthday"
|
||||
label="Birthday"
|
||||
name="birthday" />
|
||||
|
||||
|
||||
<sx:datetimepicker
|
||||
tooltip="Enter the time you wake up"
|
||||
label="Wake up time"
|
||||
name="wakeup"
|
||||
name="wakeup"
|
||||
type="time"/>
|
||||
|
||||
|
||||
<s:textarea
|
||||
tooltip="Enter your Biography"
|
||||
label="Biography"
|
||||
@@ -76,7 +76,7 @@
|
||||
name="region" list="{'North', 'South'}"
|
||||
value="'South'"
|
||||
doubleValue="'Florida'"
|
||||
doubleList="top == 'North' ? {'Oregon', 'Washington'} : {'Texas', 'Florida'}"
|
||||
doubleList="top == 'North' ? {'Oregon', 'Washington'} : {'Texas', 'Florida'}"
|
||||
doubleName="state"
|
||||
headerKey="-1"
|
||||
headerValue="---------- Please Select ----------"
|
||||
@@ -100,35 +100,35 @@
|
||||
|
||||
<s:file
|
||||
tooltip="Upload Your Picture"
|
||||
label="Picture"
|
||||
label="Picture"
|
||||
name="picture" />
|
||||
|
||||
|
||||
<s:optiontransferselect
|
||||
tooltip="Select Your Favourite Cartoon Characters"
|
||||
label="Favourite Cartoons Characters"
|
||||
name="leftSideCartoonCharacters"
|
||||
name="leftSideCartoonCharacters"
|
||||
leftTitle="Left Title"
|
||||
rightTitle="Right Title"
|
||||
list="{'Popeye', 'He-Man', 'Spiderman'}"
|
||||
list="{'Popeye', 'He-Man', 'Spiderman'}"
|
||||
multiple="true"
|
||||
headerKey="headerKey"
|
||||
headerValue="--- Please Select ---"
|
||||
emptyOption="true"
|
||||
doubleList="{'Superman', 'Mickey Mouse', 'Donald Duck'}"
|
||||
doubleList="{'Superman', 'Mickey Mouse', 'Donald Duck'}"
|
||||
doubleName="rightSideCartoonCharacters"
|
||||
doubleHeaderKey="doubleHeaderKey"
|
||||
doubleHeaderValue="--- Please Select ---"
|
||||
doubleHeaderValue="--- Please Select ---"
|
||||
doubleEmptyOption="true"
|
||||
doubleMultiple="true" />
|
||||
|
||||
|
||||
<s:textarea
|
||||
label="Your Thougths"
|
||||
name="thoughts"
|
||||
name="thoughts"
|
||||
tooltip="Enter your thoughts here" />
|
||||
|
||||
<s:submit onclick="alert('Custom onclick event triggered before submitting form... Press OK to continue!');" />
|
||||
|
||||
<s:submit />
|
||||
<s:reset onclick="alert('Resetting form now... Press OK to continue!');" />
|
||||
</s:form>
|
||||
|
||||
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
</head>
|
||||
<body>
|
||||
<h1>UI Tags</h1>
|
||||
|
||||
|
||||
<ul>
|
||||
<li><s:url var="url" namespace="/tags/ui" action="example" method="input" /><s:a href="%{url}">UI Example</s:a></li>
|
||||
<li><s:url var="url" namespace="/tags/ui" action="exampleVelocity" method="input" /><s:a href="%{url}">UI Example (Velocity)</s:a></li>
|
||||
@@ -16,6 +16,7 @@
|
||||
<li><s:url var="url" namespace="/tags/ui" action="showDynamicTreeAction"/><s:a href="%{url}">Tree Example (dynamic)</s:a>
|
||||
<li><s:url var="url" namespace="/tags/ui" action="showDynamicAjaxTreeAction"/><s:a href="%{url}">Tree Example (dynamic ajax loading)</s:a>
|
||||
<li><s:url var="url" value="componentTagExample.jsp"/><s:a href="%{#url}">Component Tag Example</s:a>
|
||||
<li><s:url var="url" namespace="/tags/ui" action="actionTagExample" method="input" /><s:a href="%{url}">Action Tag Example</s:a></li>
|
||||
<li><a href="datepicker/index.jsp">DateTime picker tag - Pick a date</a></li>
|
||||
<li><a href="timepicker/index.jsp">DateTime picker tag - Pick a time</a></li>
|
||||
<%--li><s:url var="url" namespace="/tags/ui" action="populateUsingIterator" method="input" /><s:a href="%{url}">UI population using iterator tag</s:a></li--%>
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package it.org.apache.struts2.showcase;
|
||||
|
||||
public class ActionTagExampleTest extends ITBaseTest {
|
||||
public void test() {
|
||||
beginAt("/tags/ui/actionTagExample!input.action");
|
||||
assertTextPresent("This text is from the called class");
|
||||
}
|
||||
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package it.org.apache.struts2.showcase;
|
||||
|
||||
public class ComponentTagExampleTest extends ITBaseTest {
|
||||
public void test() {
|
||||
beginAt("/tags/ui/componentTagExample.jsp");
|
||||
assertTextPresent("Freemarker Custom Template - parameter 'paramName' - paramValue1");
|
||||
assertTextPresent("Freemarker Custom Template - parameter 'paramName' - paramValue4");
|
||||
assertTextPresent("JSP Custom Template - parameter 'paramName' - paramValue2");
|
||||
assertTextPresent("JSP Custom Template - parameter 'paramName' - paramValue3");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package it.org.apache.struts2.showcase;
|
||||
|
||||
import net.sourceforge.jwebunit.junit.WebTestCase;
|
||||
|
||||
public abstract class ITBaseTest extends WebTestCase {
|
||||
|
||||
public void setUp() throws Exception {
|
||||
getTestContext().setBaseUrl(ParameterUtils.getBaseUrl());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package it.org.apache.struts2.showcase;
|
||||
|
||||
public class ParameterUtils {
|
||||
|
||||
public static String getBaseUrl() {
|
||||
String port = System.getProperty("http.port");
|
||||
if (port == null) {
|
||||
port = "8080";
|
||||
}
|
||||
return "http://localhost:"+port+"/struts2-showcase";
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package it.org.apache.struts2.showcase;
|
||||
|
||||
public class UITagExampleTest extends ITBaseTest {
|
||||
public void testInputForm() {
|
||||
setScriptingEnabled(false);
|
||||
beginAt("/tags/ui/example!input.action");
|
||||
assertFormPresent("exampleSubmit");
|
||||
// text box
|
||||
assertFormElementPresent("name");
|
||||
// textarea
|
||||
assertFormElementPresent("bio");
|
||||
// select
|
||||
assertFormElementPresent("favouriteColor");
|
||||
// checkbox list
|
||||
assertFormElementPresent("friends");
|
||||
// checkbox
|
||||
assertFormElementPresent("legalAge");
|
||||
|
||||
// set fields
|
||||
setTextField("name", "name");
|
||||
setTextField("bio", "bio");
|
||||
selectOption("favouriteColor", "Red");
|
||||
checkCheckbox("friends", "Patrick");
|
||||
checkCheckbox("friends", "Jason");
|
||||
checkCheckbox("legalAge");
|
||||
|
||||
submit();
|
||||
|
||||
assertTextInElement("name", "name");
|
||||
assertTextInElement("bio", "bio");
|
||||
assertTextInElement("favouriteColor", "Red");
|
||||
assertTextInElement("friends", "[Patrick, Jason]");
|
||||
assertTextInElement("legalAge", "true");
|
||||
}
|
||||
}
|
||||
+37
@@ -0,0 +1,37 @@
|
||||
package it.org.apache.struts2.showcase.staticcontent;
|
||||
|
||||
import it.org.apache.struts2.showcase.ITBaseTest;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import net.sourceforge.jwebunit.exception.TestingEngineResponseException;
|
||||
|
||||
public class StaticContentTest extends ITBaseTest {
|
||||
|
||||
public void testInvalidRersources1() throws IOException {
|
||||
try {
|
||||
beginAt("/struts..");
|
||||
fail("Previous request should have failed");
|
||||
} catch (TestingEngineResponseException ex) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
public void testInvalidRersources2() throws IOException {
|
||||
try {
|
||||
beginAt("/struts/..%252f");
|
||||
fail("Previous request should have failed");
|
||||
} catch (TestingEngineResponseException ex) {
|
||||
// ok
|
||||
}
|
||||
}
|
||||
|
||||
/*public void testInvalidRersources3() throws IOException {
|
||||
try {
|
||||
beginAt("/struts/..%252f..%252f..%252fWEB-INF/classes/org/apache/struts2/showcase/action/EmployeeAction.class/");
|
||||
fail("Previous request should have failed");
|
||||
} catch (TestingEngineResponseException ex) {
|
||||
// ok
|
||||
}
|
||||
}*/
|
||||
}
|
||||
+176
-146
@@ -1,26 +1,4 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
/*
|
||||
* Copyright 2005-2006 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*
|
||||
* $Id$
|
||||
*/
|
||||
-->
|
||||
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-assembly</artifactId>
|
||||
@@ -33,16 +11,160 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.1.2-SNAPSHOT</version>
|
||||
<version>2.1.3</version>
|
||||
</parent>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/assembly</connection>
|
||||
<developerConnection>
|
||||
scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/assembly</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/assembly</url>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/assembly</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/assembly</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/assembly</url>
|
||||
</scm>
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>j4</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.2-beta-1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>attached</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/all.xml</descriptor>
|
||||
<descriptor>src/main/assembly/lib.xml</descriptor>
|
||||
<descriptor>src/main/assembly/lib-jdk14.xml</descriptor>
|
||||
<descriptor>src/main/assembly/apps.xml</descriptor>
|
||||
<descriptor>src/main/assembly/src.xml</descriptor>
|
||||
<descriptor>src/main/assembly/docs.xml</descriptor>
|
||||
</descriptors>
|
||||
<finalName>struts-${version}</finalName>
|
||||
<outputDirectory>target/assembly/out</outputDirectory>
|
||||
<workDirectory>target/assembly/work</workDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<!-- Backported JDK 1.4 jars -->
|
||||
<dependency>
|
||||
<groupId>net.sf.retrotranslator</groupId>
|
||||
<artifactId>retrotranslator-runtime</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>backport-util-concurrent</groupId>
|
||||
<artifactId>backport-util-concurrent</artifactId>
|
||||
<version>3.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.opensymphony</groupId>
|
||||
<artifactId>xwork</artifactId>
|
||||
<version>2.1.2</version>
|
||||
<type>jar</type>
|
||||
<classifier>jdk14</classifier>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-config-browser-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-jasperreports-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-jfreechart-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-jsf-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-pell-multipart-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plexus-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-sitegraph-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-sitemesh-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-struts1-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-tiles-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-rest-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</profile>
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
@@ -109,7 +231,7 @@
|
||||
<groupId>com.opensymphony</groupId>
|
||||
<artifactId>xwork</artifactId>
|
||||
<classifier>javadoc</classifier>
|
||||
<version>2.1.1</version>
|
||||
<version>2.1.2</version>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<outputDirectory>${project.build.directory}/xwork-apidocs</outputDirectory>
|
||||
@@ -125,12 +247,9 @@
|
||||
<phase>process-resources</phase>
|
||||
<configuration>
|
||||
<tasks>
|
||||
<mkdir dir="${project.build.directory}/cwiki"/>
|
||||
<get src="http://struts.apache.org/2.x/docs.zip"
|
||||
dest="${project.build.directory}/docs.zip"
|
||||
ignoreerrors="false"/>
|
||||
<unzip src="${project.build.directory}/docs.zip"
|
||||
dest="${project.build.directory}/cwiki"/>
|
||||
<mkdir dir="${project.build.directory}/cwiki" />
|
||||
<get src="http://struts.apache.org/2.x/docs.zip" dest="${project.build.directory}/docs.zip" ignoreerrors="false" />
|
||||
<unzip src="${project.build.directory}/docs.zip" dest="${project.build.directory}/cwiki" />
|
||||
</tasks>
|
||||
</configuration>
|
||||
<goals>
|
||||
@@ -142,11 +261,19 @@
|
||||
<plugin>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.2-beta-1</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-assembly</id>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>attached</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>src/main/assembly/all.xml</descriptor>
|
||||
<descriptor>src/main/assembly/lib.xml</descriptor>
|
||||
<descriptor>src/main/assembly/lib-jdk14.xml</descriptor>
|
||||
<descriptor>src/main/assembly/apps.xml</descriptor>
|
||||
<descriptor>src/main/assembly/src.xml</descriptor>
|
||||
<descriptor>src/main/assembly/docs.xml</descriptor>
|
||||
@@ -166,6 +293,18 @@
|
||||
<artifactId>struts2-codebehind-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-convention-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-javatemplates-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
@@ -268,115 +407,6 @@
|
||||
<version>${version}</version>
|
||||
</dependency>
|
||||
|
||||
<!-- Backported JDK 1.4 jars -->
|
||||
<dependency>
|
||||
<groupId>net.sf.retrotranslator</groupId>
|
||||
<artifactId>retrotranslator-runtime</artifactId>
|
||||
<version>1.2.1</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>backport-util-concurrent</groupId>
|
||||
<artifactId>backport-util-concurrent</artifactId>
|
||||
<version>3.0</version>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.opensymphony</groupId>
|
||||
<artifactId>xwork</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<type>jar</type>
|
||||
<classifier>jdk14</classifier>
|
||||
<scope>runtime</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-config-browser-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-jasperreports-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-jfreechart-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-jsf-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-pell-multipart-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plexus-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-sitegraph-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-sitemesh-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-struts1-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-tiles-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-rest-plugin</artifactId>
|
||||
<version>${version}</version>
|
||||
<classifier>jdk14</classifier>
|
||||
</dependency>
|
||||
|
||||
|
||||
</dependencies>
|
||||
|
||||
</project>
|
||||
</project>
|
||||
@@ -127,6 +127,14 @@
|
||||
<directory>../plugins/codebehind/target/site</directory>
|
||||
<outputDirectory>docs/struts2-plugins/struts2-codebehind-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>../plugins/codebehind/target/site</directory>
|
||||
<outputDirectory>docs/struts2-plugins/struts2-javatemplates-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>../plugins/convention/target/site</directory>
|
||||
<outputDirectory>docs/struts2-plugins/struts2-convention-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>../plugins/config-browser/target/site</directory>
|
||||
<outputDirectory>docs/struts2-plugins/struts2-config-browser-plugin</outputDirectory>
|
||||
@@ -152,7 +160,7 @@
|
||||
<outputDirectory>docs/struts2-plugins/struts2-jsf-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>../plugins/jsf/target/site</directory>
|
||||
<directory>../plugins/junit/target/site</directory>
|
||||
<outputDirectory>docs/struts2-plugins/struts2-junit-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
@@ -188,7 +196,7 @@
|
||||
<outputDirectory>docs/struts2-plugins/struts2-sitemesh-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>../plugins/tiles/target/site</directory>
|
||||
<directory>../plugins/testng/target/site</directory>
|
||||
<outputDirectory>docs/struts2-plugins/struts2-testng-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
<outputDirectory>docs/struts2-plugins/struts2-jsf-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>../plugins/jsf/target/site</directory>
|
||||
<directory>../plugins/junit/target/site</directory>
|
||||
<outputDirectory>docs/struts2-plugins/struts2-junit-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
@@ -120,7 +120,7 @@
|
||||
<outputDirectory>docs/struts2-plugins/struts2-sitemesh-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
<directory>../plugins/tiles/target/site</directory>
|
||||
<directory>../plugins/testng/target/site</directory>
|
||||
<outputDirectory>docs/struts2-plugins/struts2-testng-plugin</outputDirectory>
|
||||
</fileSet>
|
||||
<fileSet>
|
||||
|
||||
+7
-8
@@ -26,7 +26,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.1.2-SNAPSHOT</version>
|
||||
<version>2.1.3</version>
|
||||
</parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
@@ -34,9 +34,9 @@
|
||||
<name>Struts 2 Core</name>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/core/</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/core/</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/core/</url>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/core</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/tags/STRUTS_2_1_3/core</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/tags/STRUTS_2_1_3/core</url>
|
||||
</scm>
|
||||
|
||||
<build>
|
||||
@@ -56,7 +56,7 @@
|
||||
<artifactItem>
|
||||
<groupId>com.opensymphony</groupId>
|
||||
<artifactId>xwork</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<version>2.1.2</version>
|
||||
<classifier>sources</classifier>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
@@ -229,7 +229,7 @@
|
||||
<dependency>
|
||||
<groupId>com.opensymphony</groupId>
|
||||
<artifactId>xwork</artifactId>
|
||||
<version>2.1.1</version>
|
||||
<version>2.1.2</version>
|
||||
</dependency>
|
||||
|
||||
<!--<dependency>-->
|
||||
@@ -241,7 +241,7 @@
|
||||
<dependency>
|
||||
<groupId>org.freemarker</groupId>
|
||||
<artifactId>freemarker</artifactId>
|
||||
<version>2.3.12</version>
|
||||
<version>2.3.13</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
@@ -392,7 +392,6 @@
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts-annotations</artifactId>
|
||||
<version>1.0.3</version>
|
||||
<scope>compile</scope>
|
||||
<optional>true</optional>
|
||||
</dependency>
|
||||
|
||||
@@ -118,9 +118,15 @@ public final class StrutsConstants {
|
||||
*/
|
||||
public static final String STRUTS_MULTIPART_PARSER = "struts.multipart.parser";
|
||||
|
||||
/** Whether Spring should autoWire or not */
|
||||
/** How Spring should autowire. Valid values are 'name', 'type', 'auto', and 'constructor' */
|
||||
public static final String STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE = "struts.objectFactory.spring.autoWire";
|
||||
|
||||
/** Whether the autowire strategy chosen by STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE is always respected. Defaults
|
||||
* to false, which is the legacy behavior that tries to determine the best strategy for the situation.
|
||||
* @since 2.1.3
|
||||
*/
|
||||
public static final String STRUTS_OBJECTFACTORY_SPRING_AUTOWIRE_ALWAYS_RESPECT = "struts.objectFactory.spring.autoWire.alwaysRespect";
|
||||
|
||||
/** Whether Spring should use its class cache or not */
|
||||
public static final String STRUTS_OBJECTFACTORY_SPRING_USE_CLASS_CACHE = "struts.objectFactory.spring.useClassCache";
|
||||
|
||||
@@ -184,4 +190,9 @@ public final class StrutsConstants {
|
||||
/** The {@link com.opensymphony.xwork2.util.PatternMatcher} implementation class */
|
||||
public static final String STRUTS_PATTERNMATCHER = "struts.patternMatcher";
|
||||
|
||||
/** The {@link org.apache.struts2.dispatcher.StaticContentLoader} implementation class */
|
||||
public static final String STRUTS_STATIC_CONTENT_LOADER = "struts.staticContentLoader";
|
||||
|
||||
/** The {@link com.opensymphony.xwork2.UnknownHandlerManager} implementation class */
|
||||
public static final String STRUTS_UNKNOWN_HANDLER_MANAGER = "struts.unknownHandlerManager";
|
||||
}
|
||||
|
||||
@@ -45,6 +45,7 @@ import org.apache.struts2.views.jsp.TagUtils;
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.ActionProxy;
|
||||
import com.opensymphony.xwork2.ActionProxyFactory;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
@@ -190,7 +191,7 @@ public class ActionComponent extends ContextBean {
|
||||
Map application = ctx.getApplication();
|
||||
|
||||
Dispatcher du = Dispatcher.getInstance();
|
||||
Map extraContext = du.createContextMap(new RequestMap(req),
|
||||
Map<String, Object> extraContext = du.createContextMap(new RequestMap(req),
|
||||
newParams,
|
||||
session,
|
||||
application,
|
||||
@@ -279,6 +280,7 @@ public class ActionComponent extends ContextBean {
|
||||
// get the old value stack from the request
|
||||
ValueStack stack = getStack();
|
||||
// execute at this point, after params have been set
|
||||
ActionInvocation inv = ActionContext.getContext().getActionInvocation();
|
||||
try {
|
||||
|
||||
proxy = actionProxyFactory.createActionProxy(namespace, actionName, methodName, createExtraContext(), executeResult, true);
|
||||
@@ -292,6 +294,9 @@ public class ActionComponent extends ContextBean {
|
||||
} finally {
|
||||
// set the old stack back on the request
|
||||
req.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
|
||||
if (inv != null) {
|
||||
ActionContext.getContext().setActionInvocation(inv);
|
||||
}
|
||||
}
|
||||
|
||||
if ((getVar() != null) && (proxy != null)) {
|
||||
|
||||
@@ -243,25 +243,84 @@ public class Component {
|
||||
return null;
|
||||
}
|
||||
|
||||
if (altSyntax()) {
|
||||
// does the expression start with %{ and end with }? if so, just cut it off!
|
||||
if (expr.startsWith("%{") && expr.endsWith("}")) {
|
||||
expr = expr.substring(2, expr.length() - 1);
|
||||
}
|
||||
}
|
||||
expr = stripExpressionIfAltSyntax(expr);
|
||||
|
||||
return getStack().findValue(expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* If altsyntax (%{...}) is applied, simply strip the "%{" and "}" off.
|
||||
* @param expr the expression (must be not null)
|
||||
* @return the stripped expression if altSyntax is enabled. Otherwise
|
||||
* the parameter expression is returned as is.
|
||||
*/
|
||||
protected String stripExpressionIfAltSyntax(String expr) {
|
||||
return stripExpressionIfAltSyntax(stack, expr);
|
||||
}
|
||||
|
||||
/**
|
||||
* If altsyntax (%{...}) is applied, simply strip the "%{" and "}" off.
|
||||
* @param stack the ValueStack where the context value is searched for.
|
||||
* @param expr the expression (must be not null)
|
||||
* @return the stripped expression if altSyntax is enabled. Otherwise
|
||||
* the parameter expression is returned as is.
|
||||
*/
|
||||
public static String stripExpressionIfAltSyntax(ValueStack stack, String expr) {
|
||||
if (altSyntax(stack)) {
|
||||
// does the expression start with %{ and end with }? if so, just cut it off!
|
||||
if (expr.startsWith("%{") && expr.endsWith("}")) {
|
||||
return expr.substring(2, expr.length() - 1);
|
||||
}
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the altSyntax enabled? [TRUE]
|
||||
* <p/>
|
||||
* @param stack the ValueStack where the context value is searched for.
|
||||
* @return true if altSyntax is activated. False otherwise.
|
||||
* See <code>struts.properties</code> where the altSyntax flag is defined.
|
||||
*/
|
||||
public static boolean altSyntax(ValueStack stack) {
|
||||
return ContextUtil.isUseAltSyntax(stack.getContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Is the altSyntax enabled? [TRUE]
|
||||
* <p/>
|
||||
* See <code>struts.properties</code> where the altSyntax flag is defined.
|
||||
*/
|
||||
public boolean altSyntax() {
|
||||
return ContextUtil.isUseAltSyntax(stack.getContext());
|
||||
return altSyntax(stack);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the sorrounding %{ } to the expression for proper processing.
|
||||
* @param expr the expression.
|
||||
* @return the modified expression if altSyntax is enabled, or the parameter
|
||||
* expression otherwise.
|
||||
*/
|
||||
protected String completeExpressionIfAltSyntax(String expr) {
|
||||
if (altSyntax()) {
|
||||
return "%{" + expr + "}";
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* This check is needed for backwards compatibility with 2.1.x
|
||||
* @param expr the expression.
|
||||
* @return the found string if altSyntax is enabled. The parameter
|
||||
* expression otherwise.
|
||||
*/
|
||||
protected String findStringIfAltSyntax(String expr) {
|
||||
if (altSyntax()) {
|
||||
return findString(expr);
|
||||
}
|
||||
return expr;
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluates the OGNL stack to find an Object value.
|
||||
* <p/>
|
||||
@@ -309,14 +368,9 @@ public class Component {
|
||||
*/
|
||||
protected Object findValue(String expr, Class toType) {
|
||||
if (altSyntax() && toType == String.class) {
|
||||
return TextParseUtil.translateVariables('%', expr, stack);
|
||||
return TextParseUtil.translateVariables('%', expr, stack);
|
||||
} else {
|
||||
if (altSyntax()) {
|
||||
// does the expression start with %{ and end with }? if so, just cut it off!
|
||||
if (expr.startsWith("%{") && expr.endsWith("}")) {
|
||||
expr = expr.substring(2, expr.length() - 1);
|
||||
}
|
||||
}
|
||||
expr = stripExpressionIfAltSyntax(expr);
|
||||
|
||||
return getStack().findValue(expr, toType);
|
||||
}
|
||||
|
||||
@@ -219,7 +219,7 @@ public class Date extends ContextBean {
|
||||
*/
|
||||
public String formatTime(TextProvider tp, java.util.Date date) {
|
||||
java.util.Date now = new java.util.Date();
|
||||
StringBuffer sb = new StringBuffer();
|
||||
StringBuilder sb = new StringBuilder();
|
||||
List args = new ArrayList();
|
||||
long secs = Math.abs((now.getTime() - date.getTime()) / 1000);
|
||||
long mins = secs / 60;
|
||||
|
||||
@@ -143,13 +143,7 @@ public abstract class DoubleListUIBean extends ListUIBean {
|
||||
}
|
||||
|
||||
if (doubleListValue != null) {
|
||||
if (altSyntax()) {
|
||||
// the same logic as with findValue(String)
|
||||
// if value start with %{ and end with }, just cut it off!
|
||||
if (doubleListValue.startsWith("%{") && doubleListValue.endsWith("}")) {
|
||||
doubleListValue = doubleListValue.substring(2, doubleListValue.length() - 1);
|
||||
}
|
||||
}
|
||||
doubleListValue = stripExpressionIfAltSyntax(doubleListValue);
|
||||
|
||||
addParameter("doubleListValue", doubleListValue);
|
||||
}else if (tmpDoubleList instanceof Map) {
|
||||
@@ -186,11 +180,7 @@ public abstract class DoubleListUIBean extends ListUIBean {
|
||||
Form form = (Form) findAncestor(Form.class);
|
||||
if (doubleId != null) {
|
||||
// this check is needed for backwards compatibility with 2.1.x
|
||||
if (altSyntax()) {
|
||||
addParameter("doubleId", findString(doubleId));
|
||||
} else {
|
||||
addParameter("doubleId", doubleId);
|
||||
}
|
||||
addParameter("doubleId", findStringIfAltSyntax(doubleId));
|
||||
} else if (form != null) {
|
||||
addParameter("doubleId", form.getParameters().get("id") + "_" +escape(this.doubleName));
|
||||
} else {
|
||||
|
||||
@@ -21,16 +21,15 @@
|
||||
|
||||
package org.apache.struts2.components;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import org.apache.struts2.components.Param.UnnamedParametric;
|
||||
import org.apache.struts2.views.annotations.StrutsTag;
|
||||
import org.apache.struts2.views.annotations.StrutsTagAttribute;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.struts2.views.annotations.StrutsTag;
|
||||
import org.apache.struts2.components.Param.UnnamedParametric;
|
||||
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
@@ -66,6 +65,10 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
* ....
|
||||
* </s:form>
|
||||
*
|
||||
* OR
|
||||
*
|
||||
* <s:fielderror fieldName="field1" />
|
||||
*
|
||||
* <!-- END SNIPPET: example -->
|
||||
* </pre>
|
||||
*
|
||||
@@ -87,7 +90,7 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
"or partial depending on param tag nested)if they exists")
|
||||
public class FieldError extends UIBean implements UnnamedParametric {
|
||||
|
||||
private List errorFieldNames = new ArrayList();
|
||||
private List<String> errorFieldNames = new ArrayList<String>();
|
||||
|
||||
public FieldError(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
|
||||
super(stack, request, response);
|
||||
@@ -99,14 +102,27 @@ public class FieldError extends UIBean implements UnnamedParametric {
|
||||
return TEMPLATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void evaluateExtraParams() {
|
||||
super.evaluateExtraParams();
|
||||
|
||||
if (errorFieldNames != null)
|
||||
addParameter("errorFieldNames", errorFieldNames);
|
||||
}
|
||||
|
||||
public void addParameter(Object value) {
|
||||
if (value != null) {
|
||||
errorFieldNames.add(value.toString());
|
||||
}
|
||||
}
|
||||
|
||||
public List getFieldErrorFieldNames() {
|
||||
public List<String> getFieldErrorFieldNames() {
|
||||
return errorFieldNames;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Field name for single field attribute usage", type="String")
|
||||
public void setFieldName(String fieldName) {
|
||||
addParameter(fieldName);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -93,6 +93,7 @@ public class Form extends ClosingUIBean {
|
||||
private int sequence = 0;
|
||||
|
||||
protected String onsubmit;
|
||||
protected String onreset;
|
||||
protected String action;
|
||||
protected String target;
|
||||
protected String enctype;
|
||||
@@ -103,7 +104,7 @@ public class Form extends ClosingUIBean {
|
||||
protected String windowState;
|
||||
protected String acceptcharset;
|
||||
protected String focusElement;
|
||||
|
||||
|
||||
protected Configuration configuration;
|
||||
protected ObjectFactory objectFactory;
|
||||
protected UrlRenderer urlRenderer;
|
||||
@@ -134,12 +135,12 @@ public class Form extends ClosingUIBean {
|
||||
public void setObjectFactory(ObjectFactory objectFactory) {
|
||||
this.objectFactory = objectFactory;
|
||||
}
|
||||
|
||||
|
||||
@Inject
|
||||
public void setUrlRenderer(UrlRenderer urlRenderer) {
|
||||
this.urlRenderer = urlRenderer;
|
||||
}
|
||||
|
||||
|
||||
@Inject
|
||||
public void setActionValidatorManager(ActionValidatorManager mgr) {
|
||||
this.actionValidatorManager = mgr;
|
||||
@@ -178,6 +179,10 @@ public class Form extends ClosingUIBean {
|
||||
addParameter("onsubmit", findString(onsubmit));
|
||||
}
|
||||
|
||||
if (onreset != null) {
|
||||
addParameter("onreset", findString(onreset));
|
||||
}
|
||||
|
||||
if (target != null) {
|
||||
addParameter("target", findString(target));
|
||||
}
|
||||
@@ -200,7 +205,7 @@ public class Form extends ClosingUIBean {
|
||||
// we have this if check so we don't do this twice (on open and close of the template)
|
||||
addParameter("tagNames", new ArrayList());
|
||||
}
|
||||
|
||||
|
||||
if (focusElement != null) {
|
||||
addParameter("focusElement", findString(focusElement));
|
||||
}
|
||||
@@ -295,6 +300,11 @@ public class Form extends ClosingUIBean {
|
||||
this.onsubmit = onsubmit;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="HTML onreset attribute")
|
||||
public void setOnreset(String onreset) {
|
||||
this.onreset = onreset;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Set action name to submit to, without .action suffix", defaultValue="current action")
|
||||
public void setAction(String action) {
|
||||
this.action = action;
|
||||
|
||||
@@ -34,7 +34,7 @@ import com.opensymphony.xwork2.inject.Inject;
|
||||
/**
|
||||
* FormButton.
|
||||
*/
|
||||
public abstract class FormButton extends UIBean {
|
||||
public abstract class FormButton extends ClosingUIBean {
|
||||
|
||||
static final String BUTTONTYPE_INPUT = "input";
|
||||
static final String BUTTONTYPE_BUTTON = "button";
|
||||
@@ -111,11 +111,7 @@ public abstract class FormButton extends UIBean {
|
||||
String _tmp_id = "";
|
||||
if (id != null) {
|
||||
// this check is needed for backwards compatibility with 2.1.x
|
||||
if (altSyntax()) {
|
||||
_tmp_id = findString(id);
|
||||
} else {
|
||||
_tmp_id = id;
|
||||
}
|
||||
_tmp_id = findStringIfAltSyntax(id);
|
||||
}
|
||||
else {
|
||||
if (form != null && form.getParameters().get("id") != null) {
|
||||
|
||||
@@ -124,7 +124,7 @@ public class Include extends Component {
|
||||
|
||||
public boolean end(Writer writer, String body) {
|
||||
String page = findString(value, "value", "You must specify the URL to include. Example: /foo.jsp");
|
||||
StringBuffer urlBuf = new StringBuffer();
|
||||
StringBuilder urlBuf = new StringBuilder();
|
||||
|
||||
// Add URL
|
||||
urlBuf.append(page);
|
||||
@@ -212,7 +212,7 @@ public class Include extends Component {
|
||||
}
|
||||
}
|
||||
|
||||
StringBuffer flatPathBuffer = new StringBuffer();
|
||||
StringBuilder flatPathBuffer = new StringBuilder();
|
||||
|
||||
for (int i = 0; i < stack.size(); i++) {
|
||||
flatPathBuffer.append("/").append(stack.elementAt(i));
|
||||
|
||||
@@ -34,16 +34,16 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
*
|
||||
* <p>Iterator will iterate over a value. An iterable value can be either of: java.util.Collection, java.util.Iterator,
|
||||
* java.util.Enumeration, java.util.Map, array.</p> <p/> <!-- END SNIPPET: javadoc -->
|
||||
* <p>Iterator will iterate over a value. An iterable value can be any of: java.util.Collection, java.util.Iterator,
|
||||
* java.util.Enumeration, java.util.Map, or an array.</p> <p/> <!-- END SNIPPET: javadoc -->
|
||||
*
|
||||
* <!-- START SNIPPET: params -->
|
||||
*
|
||||
* <ul>
|
||||
*
|
||||
* <li>status (String) - if specified, an instanceof IteratorStatus will be pushed into stack upon each iteration</li>
|
||||
* <li>status (String) - if specified, an instance of IteratorStatus will be pushed into stack upon each iteration</li>
|
||||
*
|
||||
* <li>value (Object) - the source to iterate over, must be iteratable, else an the object itself will be put into a
|
||||
* <li>value (Object) - the source to iterate over, must be iteratable, else the object itself will be put into a
|
||||
* newly created List (see MakeIterator#convert(Object)</li>
|
||||
*
|
||||
* <li>id (String) - if specified the current iteration object will be place with this id in Struts stack's context
|
||||
@@ -73,7 +73,7 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
*
|
||||
* <p>The following example uses a {@link Bean} tag and places it into the ActionContext. The iterator tag will retrieve
|
||||
* that object from the ActionContext and then calls its getDays() method as above. The status attribute is also used to
|
||||
* create a {@link IteratorStatus} object, which in this example, its odd() method is used to alternate row
|
||||
* create an {@link IteratorStatus} object, which in this example, its odd() method is used to alternate row
|
||||
* colours:</p>
|
||||
*
|
||||
* <!-- END SNIPPET: example2description -->
|
||||
@@ -111,7 +111,7 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
*
|
||||
* <p> The next example will further demonstrate the use of the status attribute, using a DAO obtained from the action
|
||||
* class through OGNL, iterating over groups and their users (in a security context). The last() method indicates if the
|
||||
* current object is the last available in the iteration, and if not, we need to seperate the users using a comma: </p>
|
||||
* current object is the last available in the iteration, and if not, we need to separate the users using a comma: </p>
|
||||
*
|
||||
* <!-- END SNIPPET: example3description -->
|
||||
*
|
||||
@@ -175,13 +175,32 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
* <s:property value="#stat.index" />
|
||||
*
|
||||
* <!-- grab the top of the stack which should be the -->
|
||||
* <!-- current iteration value (0, 1, ... 5) -->
|
||||
* <!-- current iteration value (1, ... 5) -->
|
||||
* <s:property value="top" />
|
||||
* </s:iterator>
|
||||
*
|
||||
* <!-- END SNIPPET: example5code -->
|
||||
* </pre>
|
||||
*
|
||||
* <!-- START SNIPPET: example6description -->
|
||||
*
|
||||
* </p>Another way to create a simple loop, similar to JSTL's
|
||||
* <c:forEach begin="..." end="..." ...> is to use some
|
||||
* OGNL magic, which provides some under-the-covers magic to
|
||||
* make 0-n loops trivial. This example also loops five times.
|
||||
*
|
||||
* <!-- END SNIPPET: example6description -->
|
||||
*
|
||||
* <pre>
|
||||
* <!-- START SNIPPET: example6code -->
|
||||
*
|
||||
* <s:iterator status="stat" value="(5).{ #this }" >
|
||||
* <s:property value="#stat.count" /> <!-- Note that "count" is 1-based, "index" is 0-based. -->
|
||||
* </s:iterator>
|
||||
*
|
||||
* <!-- END SNIPPET: example6code -->
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
@StrutsTag(name="iterator", tldTagClass="org.apache.struts2.views.jsp.IteratorTag", description="Iterate over a iterable value")
|
||||
public class IteratorComponent extends ContextBean {
|
||||
|
||||
@@ -88,10 +88,7 @@ public class Label extends UIBean {
|
||||
String providedLabel = TextProviderHelper.getText(key, key, stack);
|
||||
addParameter("nameValue", providedLabel);
|
||||
} else if (name != null) {
|
||||
String expr = name;
|
||||
if (altSyntax()) {
|
||||
expr = "%{" + expr + "}";
|
||||
}
|
||||
String expr = completeExpressionIfAltSyntax(name);
|
||||
addParameter("nameValue", findString(expr));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
*
|
||||
* Note that the listkey and listvalue attribute will default to "key" and "value"
|
||||
* respectively only when the list attribute is evaluated to a Map or its decendant.
|
||||
* Other thing else, will result in listkey and listvalue to be null and not used.
|
||||
* Everything else will result in listkey and listvalue to be null and not used.
|
||||
*
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*
|
||||
@@ -103,19 +103,14 @@ public abstract class ListUIBean extends UIBean {
|
||||
}
|
||||
|
||||
if (listKey != null) {
|
||||
listKey = stripExpressionIfAltSyntax(listKey);
|
||||
addParameter("listKey", listKey);
|
||||
} else if (value instanceof Map) {
|
||||
addParameter("listKey", "key");
|
||||
}
|
||||
|
||||
if (listValue != null) {
|
||||
if (altSyntax()) {
|
||||
// the same logic as with findValue(String)
|
||||
// if value start with %{ and end with }, just cut it off!
|
||||
if (listValue.startsWith("%{") && listValue.endsWith("}")) {
|
||||
listValue = listValue.substring(2, listValue.length() - 1);
|
||||
}
|
||||
}
|
||||
listValue = stripExpressionIfAltSyntax(listValue);
|
||||
addParameter("listValue", listValue);
|
||||
} else if (value instanceof Map) {
|
||||
addParameter("listValue", "value");
|
||||
|
||||
@@ -99,6 +99,7 @@ public class Property extends Component {
|
||||
private String defaultValue;
|
||||
private String value;
|
||||
private boolean escape = true;
|
||||
private boolean escapeJavaScript = false;
|
||||
|
||||
@StrutsTagAttribute(description="The default value to be used if <u>value</u> attribute is null")
|
||||
public void setDefault(String defaultValue) {
|
||||
@@ -110,6 +111,11 @@ public class Property extends Component {
|
||||
this.escape = escape;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Whether to escape Javascript", type="Boolean", defaultValue="false")
|
||||
public void setEscapeJavaScript(boolean escapeJavaScript) {
|
||||
this.escapeJavaScript = escapeJavaScript;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Value to be displayed", type="Object", defaultValue="<top of stack>")
|
||||
public void setValue(String value) {
|
||||
this.value = value;
|
||||
@@ -123,12 +129,8 @@ public class Property extends Component {
|
||||
if (value == null) {
|
||||
value = "top";
|
||||
}
|
||||
else if (altSyntax()) {
|
||||
// the same logic as with findValue(String)
|
||||
// if value start with %{ and end with }, just cut it off!
|
||||
if (value.startsWith("%{") && value.endsWith("}")) {
|
||||
value = value.substring(2, value.length() - 1);
|
||||
}
|
||||
else {
|
||||
value = stripExpressionIfAltSyntax(value);
|
||||
}
|
||||
|
||||
// exception: don't call findString(), since we don't want the
|
||||
@@ -150,10 +152,13 @@ public class Property extends Component {
|
||||
}
|
||||
|
||||
private String prepare(String value) {
|
||||
String result = value;
|
||||
if (escape) {
|
||||
return TextUtils.htmlEncode(value);
|
||||
} else {
|
||||
return value;
|
||||
result = TextUtils.htmlEncode(result);
|
||||
}
|
||||
if (escapeJavaScript) {
|
||||
result = TextUtils.escapeJavaScript(result);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -74,6 +74,9 @@ public class Reset extends FormButton {
|
||||
super(stack, request, response);
|
||||
}
|
||||
|
||||
public String getDefaultOpenTemplate() {
|
||||
return "empty";
|
||||
}
|
||||
protected String getDefaultTemplate() {
|
||||
return Reset.TEMPLATE;
|
||||
}
|
||||
|
||||
@@ -82,7 +82,7 @@ public class ServletUrlRenderer implements UrlRenderer {
|
||||
result = UrlHelper.buildUrl(_value, urlComponent.req, urlComponent.res, urlComponent.parameters, scheme, urlComponent.includeContext, urlComponent.encode, urlComponent.forceAddSchemeHostAndPort, urlComponent.escapeAmp);
|
||||
}
|
||||
if ( urlComponent.anchor != null && urlComponent.anchor.length() > 0 ) {
|
||||
result += '#' + urlComponent.anchor;
|
||||
result += '#' + urlComponent.findString(urlComponent.anchor);
|
||||
}
|
||||
|
||||
String var = urlComponent.getVar();
|
||||
@@ -131,10 +131,10 @@ public class ServletUrlRenderer implements UrlRenderer {
|
||||
String actionMethod = nameMapping.getMethod();
|
||||
|
||||
final ActionConfig actionConfig = formComponent.configuration.getRuntimeConfiguration().getActionConfig(
|
||||
namespace, action);
|
||||
namespace, actionName);
|
||||
if (actionConfig != null) {
|
||||
|
||||
ActionMapping mapping = new ActionMapping(action, namespace, actionMethod, formComponent.parameters);
|
||||
ActionMapping mapping = new ActionMapping(actionName, namespace, actionMethod, formComponent.parameters);
|
||||
String result = UrlHelper.buildUrl(formComponent.actionMapper.getUriFromActionMapping(mapping),
|
||||
formComponent.request, formComponent.response, null);
|
||||
formComponent.addParameter("action", result);
|
||||
@@ -153,14 +153,14 @@ public class ServletUrlRenderer implements UrlRenderer {
|
||||
|
||||
// if the name isn't specified, use the action name
|
||||
if (formComponent.name == null) {
|
||||
formComponent.addParameter("name", action);
|
||||
formComponent.addParameter("name", actionName);
|
||||
}
|
||||
|
||||
// if the id isn't specified, use the action name
|
||||
if (formComponent.getId() == null && action!=null ) {
|
||||
formComponent.addParameter("id", formComponent.escape(action));
|
||||
if (formComponent.getId() == null && actionName!=null ) {
|
||||
formComponent.addParameter("id", formComponent.escape(actionName));
|
||||
}
|
||||
} else if (action != null) {
|
||||
} else if (actionName != null) {
|
||||
// Since we can't find an action alias in the configuration, we just
|
||||
// assume the action attribute supplied is the path to be used as
|
||||
// the URI this form is submitting to.
|
||||
@@ -168,10 +168,10 @@ public class ServletUrlRenderer implements UrlRenderer {
|
||||
// Warn user that the specified namespace/action combo
|
||||
// was not found in the configuration.
|
||||
if (namespace != null) {
|
||||
LOG.warn("No configuration found for the specified action: '" + action + "' in namespace: '" + namespace + "'. Form action defaulting to 'action' attribute's literal value.");
|
||||
LOG.warn("No configuration found for the specified action: '" + actionName + "' in namespace: '" + namespace + "'. Form action defaulting to 'action' attribute's literal value.");
|
||||
}
|
||||
|
||||
String result = UrlHelper.buildUrl(action, formComponent.request, formComponent.response, null);
|
||||
String result = UrlHelper.buildUrl(actionName, formComponent.request, formComponent.response, null);
|
||||
formComponent.addParameter("action", result);
|
||||
|
||||
// namespace: cut out anything between the start and the last /
|
||||
|
||||
@@ -52,15 +52,20 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
description="Render a submit button",
|
||||
allowDynamicAttributes=true)
|
||||
public class Submit extends FormButton {
|
||||
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(Submit.class);
|
||||
final public static String TEMPLATE = "submit";
|
||||
final public static String OPEN_TEMPLATE = "submit";
|
||||
final public static String TEMPLATE = "submit-close";
|
||||
protected String src;
|
||||
|
||||
public Submit(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
|
||||
super(stack, request, response);
|
||||
}
|
||||
|
||||
public String getDefaultOpenTemplate() {
|
||||
return OPEN_TEMPLATE;
|
||||
}
|
||||
|
||||
protected String getDefaultTemplate() {
|
||||
return TEMPLATE;
|
||||
}
|
||||
@@ -76,10 +81,10 @@ public class Submit extends FormButton {
|
||||
|
||||
super.evaluateParams();
|
||||
}
|
||||
|
||||
|
||||
public void evaluateExtraParams() {
|
||||
super.evaluateExtraParams();
|
||||
|
||||
|
||||
if (src != null)
|
||||
addParameter("src", findString(src));
|
||||
}
|
||||
@@ -92,12 +97,18 @@ public class Submit extends FormButton {
|
||||
protected boolean supportsImageType() {
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@StrutsTagAttribute(description="Supply an image src for <i>image</i> type submit button. Will have no effect for types <i>input</i> and <i>button</i>.")
|
||||
public void setSrc(String src) {
|
||||
this.src = src;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public boolean usesBody() {
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Overrides to be able to render body in a template rather than always before the template
|
||||
*/
|
||||
@@ -105,7 +116,7 @@ public class Submit extends FormButton {
|
||||
evaluateParams();
|
||||
try {
|
||||
addParameter("body", body);
|
||||
|
||||
|
||||
mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate()));
|
||||
} catch (Exception e) {
|
||||
LOG.error("error when rendering", e);
|
||||
|
||||
@@ -50,8 +50,10 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
*
|
||||
* <p/>
|
||||
*
|
||||
* If the named message is not found, then the body of the tag will be used as default message.
|
||||
* If no body is used, then the name of the message will be used.
|
||||
* If the named message is not found in a property file, then the body of the
|
||||
* tag will be used as default message. If no body is used, then the stack will
|
||||
* be searched, and if a value is returned, it will written to the output.
|
||||
* If no value is found on the stack, the key of the message will be written out.
|
||||
*
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*
|
||||
@@ -123,6 +125,7 @@ public class Text extends ContextBean implements Param.UnnamedParametric {
|
||||
protected List values = Collections.EMPTY_LIST;
|
||||
protected String actualName;
|
||||
protected String name;
|
||||
protected String searchStack;
|
||||
|
||||
public Text(ValueStack stack) {
|
||||
super(stack);
|
||||
@@ -133,6 +136,10 @@ public class Text extends ContextBean implements Param.UnnamedParametric {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Search the stack if property is not found on resources", type = "Boolean", defaultValue = "true")
|
||||
public void setSearchValueStack(String searchStack) {
|
||||
this.searchStack = searchStack;
|
||||
}
|
||||
|
||||
public boolean usesBody() {
|
||||
// overriding this to true such that EVAL_BODY_BUFFERED is return and
|
||||
@@ -150,7 +157,8 @@ public class Text extends ContextBean implements Param.UnnamedParametric {
|
||||
defaultMessage = actualName;
|
||||
}
|
||||
|
||||
String msg = TextProviderHelper.getText(actualName, defaultMessage, values, getStack());
|
||||
Boolean doSearchStack = searchStack != null ? (Boolean) findValue(searchStack, Boolean.class) : true;
|
||||
String msg = TextProviderHelper.getText(actualName, defaultMessage, values, getStack(), doSearchStack == null || doSearchStack);
|
||||
|
||||
if (msg != null) {
|
||||
try {
|
||||
|
||||
@@ -32,6 +32,7 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.StrutsException;
|
||||
import org.apache.struts2.util.TextProviderHelper;
|
||||
import org.apache.struts2.components.template.Template;
|
||||
import org.apache.struts2.components.template.TemplateEngine;
|
||||
@@ -511,7 +512,7 @@ public abstract class UIBean extends Component {
|
||||
super.end(writer, body, false);
|
||||
mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate()));
|
||||
} catch (Exception e) {
|
||||
LOG.error("error when rendering", e);
|
||||
throw new StrutsException(e);
|
||||
}
|
||||
finally {
|
||||
popComponentStack();
|
||||
@@ -763,10 +764,7 @@ public abstract class UIBean extends Component {
|
||||
if (value != null) {
|
||||
addParameter("nameValue", findValue(value, valueClazz));
|
||||
} else if (name != null) {
|
||||
String expr = name;
|
||||
if (altSyntax()) {
|
||||
expr = "%{" + expr + "}";
|
||||
}
|
||||
String expr = completeExpressionIfAltSyntax(name);
|
||||
|
||||
addParameter("nameValue", findValue(expr, valueClazz));
|
||||
}
|
||||
@@ -858,7 +856,7 @@ public abstract class UIBean extends Component {
|
||||
evaluateExtraParams();
|
||||
}
|
||||
|
||||
protected String escape(String name) {
|
||||
protected String escape(String name) {
|
||||
// escape any possible values that can make the ID painful to work with in JavaScript
|
||||
if (name != null) {
|
||||
return name.replaceAll("[^a-zA-Z0-9_]", "_");
|
||||
@@ -965,11 +963,7 @@ public abstract class UIBean extends Component {
|
||||
String tryId;
|
||||
if (id != null) {
|
||||
// this check is needed for backwards compatibility with 2.1.x
|
||||
if (altSyntax()) {
|
||||
tryId = findString(id);
|
||||
} else {
|
||||
tryId = id;
|
||||
}
|
||||
tryId = findStringIfAltSyntax(id);
|
||||
} else if (form != null) {
|
||||
tryId = form.getParameters().get("id") + "_"
|
||||
+ escape(name != null ? findString(name) : null);
|
||||
@@ -1044,12 +1038,12 @@ public abstract class UIBean extends Component {
|
||||
this.disabled = disabled;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="Label expression used for rendering a element specific label")
|
||||
@StrutsTagAttribute(description="Label expression used for rendering an element specific label")
|
||||
public void setLabel(String label) {
|
||||
this.label = label;
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="String that will be appended to the labe", defaultValue=":")
|
||||
@StrutsTagAttribute(description="String that will be appended to the label", defaultValue=":")
|
||||
public void setLabelSeparator(String labelseparator) {
|
||||
this.labelSeparator = labelseparator;
|
||||
}
|
||||
|
||||
@@ -46,17 +46,17 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
* <p>This tag is used to create a URL.</p>
|
||||
*
|
||||
* <p>You can use the <param> tag inside the body to provide
|
||||
* additional request parameters. If the value of a param is an Array or
|
||||
* additional request parameters. If the value of a param is an Array or
|
||||
* an Iterable all the values will be added to the URL.</p>
|
||||
*
|
||||
* <b>NOTE:</b>
|
||||
* <p>By default request parameters will be separated using escaped ampersands (i.e., &amp;).
|
||||
* This is necessary for XHTML compliance, however, when using the URL generated by this tag
|
||||
* with the <s:property> tag, the <b>escapeAmp</b> attribute should be used to disable
|
||||
* ampersand escaping.</p>
|
||||
*
|
||||
* ampersand escaping.</p>
|
||||
*
|
||||
* <b>NOTE:</b>
|
||||
* <p>When includeParams is 'all' or 'get', the parameter defined in a <param>
|
||||
* <p>When includeParams is 'all' or 'get', the parameter defined in a <param>
|
||||
* tag will take precedence over any params included due to the includeParams attribute. For
|
||||
* example, in Example 3 below, if there is a id parameter in the url where the page this
|
||||
* tag is included like http://<host>:<port>/<context>/editUser.action?id=3333&name=John
|
||||
@@ -163,7 +163,7 @@ public class URL extends ContextBean {
|
||||
public void setUrlIncludeParams(String urlIncludeParams) {
|
||||
this.urlIncludeParams = urlIncludeParams;
|
||||
}
|
||||
|
||||
|
||||
@Inject
|
||||
public void setUrlRenderer(UrlRenderer urlRenderer) {
|
||||
this.urlRenderer = urlRenderer;
|
||||
@@ -185,7 +185,7 @@ public class URL extends ContextBean {
|
||||
return super.end(writer, body);
|
||||
}
|
||||
|
||||
@StrutsTagAttribute(description="The includeParams attribute may have the value 'none', 'get' or 'all'", defaultValue="get")
|
||||
@StrutsTagAttribute(description="The includeParams attribute may have the value 'none', 'get' or 'all'", defaultValue="none")
|
||||
public void setIncludeParams(String includeParams) {
|
||||
this.includeParams = includeParams;
|
||||
}
|
||||
@@ -244,7 +244,7 @@ public class URL extends ContextBean {
|
||||
public void setAnchor(String anchor) {
|
||||
this.anchor = anchor;
|
||||
}
|
||||
|
||||
|
||||
@StrutsTagAttribute(description="Specifies whether to escape ampersand (&) to (&amp;) or not", type="Boolean", defaultValue="true")
|
||||
public void setEscapeAmp(boolean escapeAmp) {
|
||||
this.escapeAmp = escapeAmp;
|
||||
|
||||
+21
-32
@@ -23,10 +23,9 @@ package org.apache.struts2.components.template;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.Writer;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
import java.util.concurrent.CopyOnWriteArraySet;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
@@ -55,8 +54,8 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
|
||||
static Class bodyContent = null;
|
||||
private FreemarkerManager freemarkerManager;
|
||||
|
||||
private final HashMap<String, freemarker.template.Template> templates = new HashMap<String, freemarker.template.Template>();
|
||||
private final HashSet<String> missingTemplates = new HashSet<String>();
|
||||
private final Map<String, freemarker.template.Template> templates = new ConcurrentHashMap<String, freemarker.template.Template>();
|
||||
private final Set<String> missingTemplates = new CopyOnWriteArraySet<String>();
|
||||
private boolean freemarkerCaching = false;
|
||||
|
||||
static {
|
||||
@@ -163,22 +162,20 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
|
||||
// the BodyContent JSP writer doesn't like it when FM flushes automatically --
|
||||
// so let's just not do it (it will be flushed eventually anyway)
|
||||
Writer writer = templateContext.getWriter();
|
||||
if (bodyContent != null && bodyContent.isAssignableFrom(writer.getClass())) {
|
||||
final Writer wrapped = writer;
|
||||
writer = new Writer() {
|
||||
public void write(char cbuf[], int off, int len) throws IOException {
|
||||
wrapped.write(cbuf, off, len);
|
||||
}
|
||||
final Writer wrapped = writer;
|
||||
writer = new Writer() {
|
||||
public void write(char cbuf[], int off, int len) throws IOException {
|
||||
wrapped.write(cbuf, off, len);
|
||||
}
|
||||
|
||||
public void flush() throws IOException {
|
||||
// nothing!
|
||||
}
|
||||
public void flush() throws IOException {
|
||||
// nothing!
|
||||
}
|
||||
|
||||
public void close() throws IOException {
|
||||
wrapped.close();
|
||||
}
|
||||
};
|
||||
}
|
||||
public void close() throws IOException {
|
||||
wrapped.close();
|
||||
}
|
||||
};
|
||||
|
||||
try {
|
||||
stack.push(templateContext.getTag());
|
||||
@@ -193,28 +190,20 @@ public class FreemarkerTemplateEngine extends BaseTemplateEngine {
|
||||
}
|
||||
|
||||
protected void addToMissingTemplateCache(String templateName) {
|
||||
synchronized(missingTemplates) {
|
||||
missingTemplates.add(templateName);
|
||||
}
|
||||
missingTemplates.add(templateName);
|
||||
}
|
||||
|
||||
protected boolean isTemplateMissing(String templateName) {
|
||||
synchronized(missingTemplates) {
|
||||
return missingTemplates.contains(templateName);
|
||||
}
|
||||
return missingTemplates.contains(templateName);
|
||||
}
|
||||
|
||||
protected void addToCache(String templateName,
|
||||
freemarker.template.Template template) {
|
||||
synchronized(templates) {
|
||||
templates.put(templateName, template);
|
||||
}
|
||||
templates.put(templateName, template);
|
||||
}
|
||||
|
||||
protected freemarker.template.Template findInCache(String templateName) {
|
||||
synchronized(templates) {
|
||||
return templates.get(templateName);
|
||||
}
|
||||
return templates.get(templateName);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,6 +26,8 @@ import java.util.StringTokenizer;
|
||||
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.components.UrlRenderer;
|
||||
import org.apache.struts2.dispatcher.DefaultStaticContentLoader;
|
||||
import org.apache.struts2.dispatcher.StaticContentLoader;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapper;
|
||||
import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
|
||||
import org.apache.struts2.views.freemarker.FreemarkerManager;
|
||||
@@ -34,6 +36,7 @@ import org.apache.struts2.views.velocity.VelocityManager;
|
||||
import com.opensymphony.xwork2.ActionProxyFactory;
|
||||
import com.opensymphony.xwork2.ObjectFactory;
|
||||
import com.opensymphony.xwork2.TextProvider;
|
||||
import com.opensymphony.xwork2.UnknownHandlerManager;
|
||||
import com.opensymphony.xwork2.config.Configuration;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.config.ConfigurationProvider;
|
||||
@@ -44,10 +47,7 @@ import com.opensymphony.xwork2.inject.ContainerBuilder;
|
||||
import com.opensymphony.xwork2.inject.Context;
|
||||
import com.opensymphony.xwork2.inject.Factory;
|
||||
import com.opensymphony.xwork2.inject.Scope;
|
||||
import com.opensymphony.xwork2.util.ClassLoaderUtil;
|
||||
import com.opensymphony.xwork2.util.LocalizedTextUtil;
|
||||
import com.opensymphony.xwork2.util.PatternMatcher;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
import com.opensymphony.xwork2.util.*;
|
||||
import com.opensymphony.xwork2.util.location.LocatableProperties;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
@@ -151,6 +151,12 @@ import com.opensymphony.xwork2.validator.ActionValidatorManager;
|
||||
* <td>singleton</td>
|
||||
* <td>Matches patterns, such as action names, generally used in configuration (since 2.1)</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>org.apache.struts2.views.dispatcher.DefaultStaticContentLoader</td>
|
||||
* <td>struts.staticContentLoader</td>
|
||||
* <td>singleton</td>
|
||||
* <td>Loads static resources (since 2.1)</td>
|
||||
* </tr>
|
||||
* </table>
|
||||
*
|
||||
* <!-- END SNIPPET: extensionPoints -->
|
||||
@@ -209,6 +215,8 @@ public class BeanSelectionProvider implements ConfigurationProvider {
|
||||
alias(ReflectionProvider.class, StrutsConstants.STRUTS_REFLECTIONPROVIDER, builder, props);
|
||||
alias(ReflectionContextFactory.class, StrutsConstants.STRUTS_REFLECTIONCONTEXTFACTORY, builder, props);
|
||||
alias(PatternMatcher.class, StrutsConstants.STRUTS_PATTERNMATCHER, builder, props);
|
||||
alias(StaticContentLoader.class, StrutsConstants.STRUTS_STATIC_CONTENT_LOADER, builder, props);
|
||||
alias(UnknownHandlerManager.class, StrutsConstants.STRUTS_UNKNOWN_HANDLER_MANAGER, builder, props);
|
||||
|
||||
if ("true".equalsIgnoreCase(props.getProperty(StrutsConstants.STRUTS_DEVMODE))) {
|
||||
props.setProperty(StrutsConstants.STRUTS_I18N_RELOAD, "true");
|
||||
|
||||
@@ -77,6 +77,7 @@ public class StrutsXmlConfigurationProvider extends XmlConfigurationProvider {
|
||||
reloadKey = "configurationReload-"+filename;
|
||||
Map<String,String> dtdMappings = new HashMap<String,String>(getDtdMappings());
|
||||
dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.0//EN", "struts-2.0.dtd");
|
||||
dtdMappings.put("-//Apache Software Foundation//DTD Struts Configuration 2.1//EN", "struts-2.1.dtd");
|
||||
setDtdMappings(dtdMappings);
|
||||
File file = new File(filename);
|
||||
if (file.getParent() != null) {
|
||||
|
||||
@@ -59,8 +59,13 @@ import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
|
||||
* <!-- SNIPPET END: description -->
|
||||
*
|
||||
*
|
||||
* @deprecated Since Struts 2.1.3, use {@link org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter} and
|
||||
* {@link org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter} to use other Servlet filters that need access to
|
||||
* the ActionContext
|
||||
* @see FilterDispatcher
|
||||
* @see Dispatcher
|
||||
* @see org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter
|
||||
* @see org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter
|
||||
*
|
||||
* @version $Date$ $Id$
|
||||
*/
|
||||
|
||||
@@ -0,0 +1,356 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.net.URL;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.List;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.dispatcher.ng.HostConfig;
|
||||
import org.apache.struts2.util.ClassLoaderUtils;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ClassLoaderUtil;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
public class DefaultStaticContentLoader implements StaticContentLoader {
|
||||
/**
|
||||
* Provide a logging instance.
|
||||
*/
|
||||
private Logger log;
|
||||
|
||||
/**
|
||||
* Store set of path prefixes to use with static resources.
|
||||
*/
|
||||
protected String[] pathPrefixes;
|
||||
|
||||
/**
|
||||
* Store state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
|
||||
*/
|
||||
protected boolean serveStatic;
|
||||
|
||||
/**
|
||||
* Store state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE setting.
|
||||
*/
|
||||
protected boolean serveStaticBrowserCache;
|
||||
|
||||
/**
|
||||
* Provide a formatted date for setting heading information when caching static content.
|
||||
*/
|
||||
protected final Calendar lastModifiedCal = Calendar.getInstance();
|
||||
|
||||
/**
|
||||
* Store state of StrutsConstants.STRUTS_I18N_ENCODING setting.
|
||||
*/
|
||||
protected String encoding;
|
||||
|
||||
|
||||
/**
|
||||
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
|
||||
*
|
||||
* @param val
|
||||
* New setting
|
||||
*/
|
||||
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_CONTENT)
|
||||
public void setServeStaticContent(String val) {
|
||||
serveStatic = "true".equals(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE
|
||||
* setting.
|
||||
*
|
||||
* @param val
|
||||
* New setting
|
||||
*/
|
||||
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE)
|
||||
public void setServeStaticBrowserCache(String val) {
|
||||
serveStaticBrowserCache = "true".equals(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting.
|
||||
* @param val New setting
|
||||
*/
|
||||
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
|
||||
public void setEncoding(String val) {
|
||||
encoding = val;
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.apache.struts2.dispatcher.StaticResourceLoader#setHostConfig(javax.servlet.FilterConfig)
|
||||
*/
|
||||
public void setHostConfig(HostConfig filterConfig) {
|
||||
String param = filterConfig.getInitParameter("packages");
|
||||
String packages = getAdditionalPackages();
|
||||
if (param != null) {
|
||||
packages = param + " " + packages;
|
||||
}
|
||||
this.pathPrefixes = parse(packages);
|
||||
initLogging(filterConfig);
|
||||
}
|
||||
|
||||
protected String getAdditionalPackages() {
|
||||
return "org.apache.struts2.static template org.apache.struts2.interceptor.debugging static";
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a string array from a comma-delimited list of packages.
|
||||
*
|
||||
* @param packages
|
||||
* A comma-delimited String listing packages
|
||||
* @return A string array of packages
|
||||
*/
|
||||
protected String[] parse(String packages) {
|
||||
if (packages == null) {
|
||||
return null;
|
||||
}
|
||||
List<String> pathPrefixes = new ArrayList<String>();
|
||||
|
||||
StringTokenizer st = new StringTokenizer(packages, ", \n\t");
|
||||
while (st.hasMoreTokens()) {
|
||||
String pathPrefix = st.nextToken().replace('.', '/');
|
||||
if (!pathPrefix.endsWith("/")) {
|
||||
pathPrefix += "/";
|
||||
}
|
||||
pathPrefixes.add(pathPrefix);
|
||||
}
|
||||
|
||||
return pathPrefixes.toArray(new String[pathPrefixes.size()]);
|
||||
}
|
||||
|
||||
/*
|
||||
* (non-Javadoc)
|
||||
*
|
||||
* @see org.apache.struts2.dispatcher.StaticResourceLoader#findStaticResource(java.lang.String,
|
||||
* javax.servlet.http.HttpServletRequest,
|
||||
* javax.servlet.http.HttpServletResponse)
|
||||
*/
|
||||
public void findStaticResource(String path, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException {
|
||||
String name = cleanupPath(path);
|
||||
for (String pathPrefix : pathPrefixes) {
|
||||
URL resourceUrl = findResource(buildPath(name, pathPrefix));
|
||||
if (resourceUrl != null) {
|
||||
InputStream is = null;
|
||||
try {
|
||||
//check that the resource path is under the pathPrefix path
|
||||
String pathEnding = buildPath(name, pathPrefix);
|
||||
if (resourceUrl.getFile().endsWith(pathEnding))
|
||||
is = resourceUrl.openStream();
|
||||
} catch (Exception ex) {
|
||||
// just ignore it
|
||||
continue;
|
||||
}
|
||||
|
||||
//not inside the try block, as this could throw IOExceptions also
|
||||
if (is != null) {
|
||||
process(is, path, request, response);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
|
||||
protected void process(InputStream is, String path, HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
if (is != null) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
|
||||
// check for if-modified-since, prior to any other headers
|
||||
long ifModifiedSince = 0;
|
||||
try {
|
||||
ifModifiedSince = request.getDateHeader("If-Modified-Since");
|
||||
} catch (Exception e) {
|
||||
log.warn("Invalid If-Modified-Since header value: '"
|
||||
+ request.getHeader("If-Modified-Since") + "', ignoring");
|
||||
}
|
||||
long lastModifiedMillis = lastModifiedCal.getTimeInMillis();
|
||||
long now = cal.getTimeInMillis();
|
||||
cal.add(Calendar.DAY_OF_MONTH, 1);
|
||||
long expires = cal.getTimeInMillis();
|
||||
|
||||
if (ifModifiedSince > 0 && ifModifiedSince <= lastModifiedMillis) {
|
||||
// not modified, content is not sent - only basic
|
||||
// headers and status SC_NOT_MODIFIED
|
||||
response.setDateHeader("Expires", expires);
|
||||
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
is.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// set the content-type header
|
||||
String contentType = getContentType(path);
|
||||
if (contentType != null) {
|
||||
response.setContentType(contentType);
|
||||
}
|
||||
|
||||
if (serveStaticBrowserCache) {
|
||||
// set heading information for caching static content
|
||||
response.setDateHeader("Date", now);
|
||||
response.setDateHeader("Expires", expires);
|
||||
response.setDateHeader("Retry-After", expires);
|
||||
response.setHeader("Cache-Control", "public");
|
||||
response.setDateHeader("Last-Modified", lastModifiedMillis);
|
||||
} else {
|
||||
response.setHeader("Cache-Control", "no-cache");
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Expires", "-1");
|
||||
}
|
||||
|
||||
try {
|
||||
copy(is, response.getOutputStream());
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void initLogging(HostConfig filterConfig) {
|
||||
String factoryName = filterConfig.getInitParameter("loggerFactory");
|
||||
if (factoryName != null) {
|
||||
try {
|
||||
Class cls = ClassLoaderUtils.loadClass(factoryName, this.getClass());
|
||||
LoggerFactory fac = (LoggerFactory)cls.newInstance();
|
||||
LoggerFactory.setLoggerFactory(fac);
|
||||
} catch (InstantiationException e) {
|
||||
System.err.println("Unable to instantiate logger factory: "+factoryName+", using default");
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
System.err.println("Unable to access logger factory: "+factoryName+", using default");
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("Unable to locate logger factory class: "+factoryName+", using default");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
log = LoggerFactory.getLogger(FilterDispatcher.class);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a static resource in the classpath.
|
||||
*
|
||||
* @param path The resource path
|
||||
* @return The inputstream of the resource
|
||||
* @throws IOException If there is a problem locating the resource
|
||||
*/
|
||||
protected URL findResource(String path) throws IOException {
|
||||
return ClassLoaderUtil.getResource(path, getClass());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name resource name
|
||||
* @param packagePrefix The package prefix to use to locate the resource
|
||||
* @return full path
|
||||
* @throws UnsupportedEncodingException
|
||||
* @throws IOException
|
||||
*/
|
||||
protected String buildPath(String name, String packagePrefix) throws UnsupportedEncodingException {
|
||||
String resourcePath;
|
||||
if (packagePrefix.endsWith("/") && name.startsWith("/")) {
|
||||
resourcePath = packagePrefix + name.substring(1);
|
||||
} else {
|
||||
resourcePath = packagePrefix + name;
|
||||
}
|
||||
|
||||
return URLDecoder.decode(resourcePath, encoding);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determine the content type for the resource name.
|
||||
*
|
||||
* @param name The resource name
|
||||
* @return The mime type
|
||||
*/
|
||||
protected String getContentType(String name) {
|
||||
// NOT using the code provided activation.jar to avoid adding yet another dependency
|
||||
// this is generally OK, since these are the main files we server up
|
||||
if (name.endsWith(".js")) {
|
||||
return "text/javascript";
|
||||
} else if (name.endsWith(".css")) {
|
||||
return "text/css";
|
||||
} else if (name.endsWith(".html")) {
|
||||
return "text/html";
|
||||
} else if (name.endsWith(".txt")) {
|
||||
return "text/plain";
|
||||
} else if (name.endsWith(".gif")) {
|
||||
return "image/gif";
|
||||
} else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
|
||||
return "image/jpeg";
|
||||
} else if (name.endsWith(".png")) {
|
||||
return "image/png";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy bytes from the input stream to the output stream.
|
||||
*
|
||||
* @param input
|
||||
* The input stream
|
||||
* @param output
|
||||
* The output stream
|
||||
* @throws IOException
|
||||
* If anything goes wrong
|
||||
*/
|
||||
protected void copy(InputStream input, OutputStream output) throws IOException {
|
||||
final byte[] buffer = new byte[4096];
|
||||
int n;
|
||||
while (-1 != (n = input.read(buffer))) {
|
||||
output.write(buffer, 0, n);
|
||||
}
|
||||
output.flush();
|
||||
}
|
||||
|
||||
public boolean canHandle(String resourcePath) {
|
||||
return serveStatic && (resourcePath.startsWith("/struts") || resourcePath.startsWith("/static"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param path requested path
|
||||
* @return path without leading "/struts" or "/static"
|
||||
*/
|
||||
protected String cleanupPath(String path) {
|
||||
//path will start with "/struts" or "/static", remove them
|
||||
return path.substring(7);
|
||||
}
|
||||
}
|
||||
@@ -24,10 +24,14 @@ package org.apache.struts2.dispatcher;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
@@ -58,10 +62,14 @@ import com.opensymphony.xwork2.config.Configuration;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.config.ConfigurationManager;
|
||||
import com.opensymphony.xwork2.config.ConfigurationProvider;
|
||||
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
|
||||
import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.inject.ContainerBuilder;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.interceptor.Interceptor;
|
||||
import com.opensymphony.xwork2.util.FileManager;
|
||||
import com.opensymphony.xwork2.util.LocalizedTextUtil;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
@@ -98,7 +106,7 @@ public class Dispatcher {
|
||||
* Store list of DispatcherListeners.
|
||||
*/
|
||||
private static List<DispatcherListener> dispatcherListeners =
|
||||
new ArrayList<DispatcherListener>();
|
||||
new CopyOnWriteArrayList<DispatcherListener>();
|
||||
|
||||
/**
|
||||
* Store ConfigurationManager instance, set on init.
|
||||
@@ -162,7 +170,7 @@ public class Dispatcher {
|
||||
*
|
||||
* @param listener The listener to add
|
||||
*/
|
||||
public static synchronized void addDispatcherListener(DispatcherListener listener) {
|
||||
public static void addDispatcherListener(DispatcherListener listener) {
|
||||
dispatcherListeners.add(listener);
|
||||
}
|
||||
|
||||
@@ -171,7 +179,7 @@ public class Dispatcher {
|
||||
*
|
||||
* @param listener The listener
|
||||
*/
|
||||
public static synchronized void removeDispatcherListener(DispatcherListener listener) {
|
||||
public static void removeDispatcherListener(DispatcherListener listener) {
|
||||
dispatcherListeners.remove(listener);
|
||||
}
|
||||
|
||||
@@ -257,13 +265,27 @@ public class Dispatcher {
|
||||
instance.set(null);
|
||||
|
||||
// clean up DispatcherListeners
|
||||
synchronized(Dispatcher.class) {
|
||||
if (dispatcherListeners.size() > 0) {
|
||||
for (DispatcherListener l : dispatcherListeners) {
|
||||
l.dispatcherDestroyed(this);
|
||||
if (!dispatcherListeners.isEmpty()) {
|
||||
for (DispatcherListener l : dispatcherListeners) {
|
||||
l.dispatcherDestroyed(this);
|
||||
}
|
||||
}
|
||||
|
||||
// clean up all interceptors by calling their destroy() method
|
||||
Set<Interceptor> interceptors = new HashSet<Interceptor>();
|
||||
Collection<PackageConfig> packageConfigs = configurationManager.getConfiguration().getPackageConfigs().values();
|
||||
for (PackageConfig packageConfig : packageConfigs) {
|
||||
for (Object config : packageConfig.getAllInterceptorConfigs().values()) {
|
||||
if (config instanceof InterceptorStackConfig) {
|
||||
for (InterceptorMapping interceptorMapping : ((InterceptorStackConfig) config).getInterceptors()) {
|
||||
interceptors.add(interceptorMapping.getInterceptor());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (Interceptor interceptor : interceptors) {
|
||||
interceptor.destroy();
|
||||
}
|
||||
|
||||
// clean up configuration
|
||||
configurationManager.destroyConfiguration();
|
||||
@@ -317,39 +339,6 @@ public class Dispatcher {
|
||||
}
|
||||
}
|
||||
|
||||
private void init_MethodConfigurationProvider() {
|
||||
// See https://issues.apache.org/struts/browse/WW-1522
|
||||
/*
|
||||
com.opensymphony.xwork2.inject.DependencyException: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyException: No mapping found for dependency [type=org.apache.struts2.dispatcher.mapper.ActionMapper, name='default'] in public static void org.apache.struts2.dispatcher.FilterDispatcher.setActionMapper(org.apache.struts2.dispatcher.mapper.ActionMapper).
|
||||
at com.opensymphony.xwork2.inject.ContainerImpl.addInjectorsForMembers(ContainerImpl.java:135)
|
||||
at com.opensymphony.xwork2.inject.ContainerImpl.addInjectorsForMethods(ContainerImpl.java:104)
|
||||
at com.opensymphony.xwork2.inject.ContainerImpl.injectStatics(ContainerImpl.java:89)
|
||||
at com.opensymphony.xwork2.inject.ContainerBuilder.create(ContainerBuilder.java:494)
|
||||
at com.opensymphony.xwork2.config.impl.DefaultConfiguration.reload(DefaultConfiguration.java:140)
|
||||
at com.opensymphony.xwork2.config.ConfigurationManager.getConfiguration(ConfigurationManager.java:52)
|
||||
at org.apache.struts2.dispatcher.Dispatcher.init_MethodConfigurationProvider(Dispatcher.java:347)
|
||||
at org.apache.struts2.dispatcher.Dispatcher.init(Dispatcher.java:421)
|
||||
at org.apache.struts2.config.MethodConfigurationProviderTest.setUp(MethodConfigurationProviderTest.java:68)
|
||||
at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:40)
|
||||
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
|
||||
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
|
||||
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
|
||||
at com.intellij.rt.execution.application.AppMain.main(AppMain.java:90)
|
||||
Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyException: No mapping found for dependency [type=org.apache.struts2.dispatcher.mapper.ActionMapper, name='default'] in public static void org.apache.struts2.dispatcher.FilterDispatcher.setActionMapper(org.apache.struts2.dispatcher.mapper.ActionMapper).
|
||||
at com.opensymphony.xwork2.inject.ContainerImpl.createParameterInjector(ContainerImpl.java:217)
|
||||
at com.opensymphony.xwork2.inject.ContainerImpl.getParametersInjectors(ContainerImpl.java:207)
|
||||
at com.opensymphony.xwork2.inject.ContainerImpl$MethodInjector.<init>(ContainerImpl.java:260)
|
||||
at com.opensymphony.xwork2.inject.ContainerImpl$3.create(ContainerImpl.java:108)
|
||||
at com.opensymphony.xwork2.inject.ContainerImpl$3.create(ContainerImpl.java:106)
|
||||
at com.opensymphony.xwork2.inject.ContainerImpl.addInjectorsForMembers(ContainerImpl.java:132)
|
||||
... 26 more
|
||||
|
||||
MethodConfigurationProvider provider = new MethodConfigurationProvider();
|
||||
provider.init(configurationManager.getConfiguration());
|
||||
provider.loadPackages();
|
||||
*/
|
||||
}
|
||||
|
||||
private void init_FilterInitParameters() {
|
||||
configurationManager.addConfigurationProvider(new ConfigurationProvider() {
|
||||
public void destroy() {}
|
||||
@@ -392,15 +381,6 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
|
||||
paramsWorkaroundEnabled = "true".equals(container.getInstance(String.class,
|
||||
StrutsConstants.STRUTS_DISPATCHER_PARAMETERSWORKAROUND));
|
||||
}
|
||||
|
||||
synchronized(Dispatcher.class) {
|
||||
if (dispatcherListeners.size() > 0) {
|
||||
for (DispatcherListener l : dispatcherListeners) {
|
||||
l.dispatcherInitialized(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -417,7 +397,6 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
|
||||
init_TraditionalXmlConfigurations(); // [2]
|
||||
init_LegacyStrutsProperties(); // [3]
|
||||
init_CustomConfigurationProviders(); // [5]
|
||||
init_MethodConfigurationProvider();
|
||||
init_FilterInitParameters() ; // [6]
|
||||
init_AliasStandardObjects() ; // [7]
|
||||
|
||||
@@ -426,6 +405,11 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
|
||||
init_CheckConfigurationReloading(container);
|
||||
init_CheckWebLogicWorkaround(container);
|
||||
|
||||
if (!dispatcherListeners.isEmpty()) {
|
||||
for (DispatcherListener l : dispatcherListeners) {
|
||||
l.dispatcherInitialized(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -452,6 +436,12 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
|
||||
|
||||
// If there was a previous value stack, then create a new copy and pass it in to be used by the new Action
|
||||
ValueStack stack = (ValueStack) request.getAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY);
|
||||
if (stack == null) {
|
||||
ActionContext ctx = ActionContext.getContext();
|
||||
if (ctx != null) {
|
||||
stack = ctx.getValueStack();
|
||||
}
|
||||
}
|
||||
if (stack != null) {
|
||||
extraContext.put(ActionContext.VALUE_STACK, valueStackFactory.createValueStack(stack));
|
||||
}
|
||||
@@ -482,7 +472,13 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
|
||||
request.setAttribute(ServletActionContext.STRUTS_VALUESTACK_KEY, stack);
|
||||
}
|
||||
} catch (ConfigurationException e) {
|
||||
LOG.error("Could not find action or result", e);
|
||||
// WW-2874 Only log error if in devMode
|
||||
if(devMode) {
|
||||
LOG.error("Could not find action or result", e);
|
||||
}
|
||||
else {
|
||||
LOG.warn("Could not find action or result", e);
|
||||
}
|
||||
sendError(request, response, context, HttpServletResponse.SC_NOT_FOUND, e);
|
||||
} catch (Exception e) {
|
||||
sendError(request, response, context, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, e);
|
||||
@@ -516,7 +512,10 @@ Caused by: com.opensymphony.xwork2.inject.ContainerImpl$MissingDependencyExcepti
|
||||
Map application = new ApplicationMap(context);
|
||||
|
||||
Map<String,Object> extraContext = createContextMap(requestMap, params, session, application, request, response, context);
|
||||
extraContext.put(ServletActionContext.ACTION_MAPPING, mapping);
|
||||
|
||||
if (mapping != null) {
|
||||
extraContext.put(ServletActionContext.ACTION_MAPPING, mapping);
|
||||
}
|
||||
return extraContext;
|
||||
}
|
||||
|
||||
|
||||
@@ -22,16 +22,9 @@
|
||||
package org.apache.struts2.dispatcher;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.net.URLDecoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.StringTokenizer;
|
||||
|
||||
import javax.servlet.Filter;
|
||||
import javax.servlet.FilterChain;
|
||||
@@ -44,18 +37,16 @@ import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.struts2.RequestUtils;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.StrutsStatics;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapper;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
import org.apache.struts2.dispatcher.ng.filter.FilterHostConfig;
|
||||
import org.apache.struts2.util.ClassLoaderUtils;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.config.Configuration;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.config.ConfigurationProvider;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ClassLoaderUtil;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
@@ -65,90 +56,96 @@ import com.opensymphony.xwork2.util.profiling.UtilTimerStack;
|
||||
/**
|
||||
* Master filter for Struts that handles four distinct
|
||||
* responsibilities:
|
||||
*
|
||||
* <p/>
|
||||
* <ul>
|
||||
*
|
||||
* <p/>
|
||||
* <li>Executing actions</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li>Cleaning up the {@link ActionContext} (see note)</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li>Serving static content</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li>Kicking off XWork's interceptor chain for the request lifecycle</li>
|
||||
*
|
||||
* <p/>
|
||||
* </ul>
|
||||
*
|
||||
* <p/>
|
||||
* <p/> <b>IMPORTANT</b>: this filter must be mapped to all requests. Unless you know exactly what you are doing, always
|
||||
* map to this URL pattern: /*
|
||||
*
|
||||
* <p/>
|
||||
* <p/> <b>Executing actions</b>
|
||||
*
|
||||
* <p/>
|
||||
* <p/> This filter executes actions by consulting the {@link ActionMapper} and determining if the requested URL should
|
||||
* invoke an action. If the mapper indicates it should, <b>the rest of the filter chain is stopped</b> and the action is
|
||||
* invoked. This is important, as it means that filters like the SiteMesh filter must be placed <b>before</b> this
|
||||
* filter or they will not be able to decorate the output of actions.
|
||||
*
|
||||
* <p/>
|
||||
* <p/> <b>Cleaning up the {@link ActionContext}</b>
|
||||
*
|
||||
* <p/>
|
||||
* <p/> This filter will also automatically clean up the {@link ActionContext} for you, ensuring that no memory leaks
|
||||
* take place. However, this can sometimes cause problems integrating with other products like SiteMesh. See {@link
|
||||
* ActionContextCleanUp} for more information on how to deal with this.
|
||||
*
|
||||
* <p/>
|
||||
* <p/> <b>Serving static content</b>
|
||||
*
|
||||
* <p/>
|
||||
* <p/> This filter also serves common static content needed when using various parts of Struts, such as JavaScript
|
||||
* files, CSS files, etc. It works by looking for requests to /struts/*, and then mapping the value after "/struts/"
|
||||
* to common packages in Struts and, optionally, in your class path. By default, the following packages are
|
||||
* automatically searched:
|
||||
*
|
||||
* <p/>
|
||||
* <ul>
|
||||
*
|
||||
* <p/>
|
||||
* <li>org.apache.struts2.static</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li>template</li>
|
||||
*
|
||||
* <p/>
|
||||
* </ul>
|
||||
*
|
||||
* <p/>
|
||||
* <p/> This means that you can simply request /struts/xhtml/styles.css and the XHTML UI theme's default stylesheet
|
||||
* will be returned. Likewise, many of the AJAX UI components require various JavaScript files, which are found in the
|
||||
* org.apache.struts2.static package. If you wish to add additional packages to be searched, you can add a comma
|
||||
* separated (space, tab and new line will do as well) list in the filter init parameter named "packages". <b>Be
|
||||
* careful</b>, however, to expose any packages that may have sensitive information, such as properties file with
|
||||
* database access credentials.
|
||||
*
|
||||
* <p/>
|
||||
*
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <p>
|
||||
*
|
||||
* <p/>
|
||||
* This filter supports the following init-params:
|
||||
* <!-- START SNIPPET: params -->
|
||||
*
|
||||
* <p/>
|
||||
* <ul>
|
||||
*
|
||||
* <p/>
|
||||
* <li><b>config</b> - a comma-delimited list of XML configuration files to load.</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li><b>actionPackages</b> - a comma-delimited list of Java packages to scan for Actions.</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li><b>configProviders</b> - a comma-delimited list of Java classes that implement the
|
||||
* {@link ConfigurationProvider} interface that should be used for building the {@link Configuration}.</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li><b>loggerFactory</b> - The class name of the {@link LoggerFactory} implementation.</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li><b>*</b> - any other parameters are treated as framework constants.</li>
|
||||
*
|
||||
* <p/>
|
||||
* </ul>
|
||||
*
|
||||
* <p/>
|
||||
* <!-- END SNIPPET: params -->
|
||||
*
|
||||
* <p/>
|
||||
* </p>
|
||||
*
|
||||
* <p/>
|
||||
* To use a custom {@link Dispatcher}, the <code>createDispatcher()</code> method could be overriden by
|
||||
* the subclass.
|
||||
*
|
||||
* @version $Date$ $Id$
|
||||
* @deprecated Since Struts 2.1.3, use {@link org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter} instead or
|
||||
* {@link org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter} and {@link org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter}
|
||||
* if needing using the {@link ActionContextCleanUp} filter in addition to this one
|
||||
*
|
||||
* @see ActionMapper
|
||||
* @see ActionContextCleanUp
|
||||
*
|
||||
* @version $Date$ $Id$
|
||||
* @see org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter
|
||||
* @see org.apache.struts2.dispatcher.ng.filter.StrutsPrepareFilter
|
||||
* @see org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter
|
||||
*/
|
||||
public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
|
||||
@@ -157,31 +154,6 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
*/
|
||||
private Logger log;
|
||||
|
||||
/**
|
||||
* Store set of path prefixes to use with static resources.
|
||||
*/
|
||||
private String[] pathPrefixes;
|
||||
|
||||
/**
|
||||
* Provide a formatted date for setting heading information when caching static content.
|
||||
*/
|
||||
private final Calendar lastModifiedCal = Calendar.getInstance();
|
||||
|
||||
/**
|
||||
* Store state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
|
||||
*/
|
||||
private boolean serveStatic;
|
||||
|
||||
/**
|
||||
* Store state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE setting.
|
||||
*/
|
||||
private boolean serveStaticBrowserCache;
|
||||
|
||||
/**
|
||||
* Store state of StrutsConstants.STRUTS_I18N_ENCODING setting.
|
||||
*/
|
||||
private String encoding;
|
||||
|
||||
/**
|
||||
* Provide ActionMapper instance, set by injection.
|
||||
*/
|
||||
@@ -197,6 +169,11 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
*/
|
||||
protected Dispatcher dispatcher;
|
||||
|
||||
/**
|
||||
* Loads stattic resources, set by injection
|
||||
*/
|
||||
protected StaticContentLoader staticResourceLoader;
|
||||
|
||||
/**
|
||||
* Initializes the filter by creating a default dispatcher
|
||||
* and setting the default packages for static resources.
|
||||
@@ -213,12 +190,7 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
dispatcher.init();
|
||||
dispatcher.getContainer().inject(this);
|
||||
|
||||
String param = filterConfig.getInitParameter("packages");
|
||||
String packages = "org.apache.struts2.static template org.apache.struts2.interceptor.debugging";
|
||||
if (param != null) {
|
||||
packages = param + " " + packages;
|
||||
}
|
||||
this.pathPrefixes = parse(packages);
|
||||
staticResourceLoader.setHostConfig(new FilterHostConfig(filterConfig));
|
||||
} finally {
|
||||
ActionContext.setContext(null);
|
||||
}
|
||||
@@ -229,22 +201,22 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
if (factoryName != null) {
|
||||
try {
|
||||
Class cls = ClassLoaderUtils.loadClass(factoryName, this.getClass());
|
||||
LoggerFactory fac = (LoggerFactory)cls.newInstance();
|
||||
LoggerFactory fac = (LoggerFactory) cls.newInstance();
|
||||
LoggerFactory.setLoggerFactory(fac);
|
||||
} catch (InstantiationException e) {
|
||||
System.err.println("Unable to instantiate logger factory: "+factoryName+", using default");
|
||||
System.err.println("Unable to instantiate logger factory: " + factoryName + ", using default");
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
System.err.println("Unable to access logger factory: "+factoryName+", using default");
|
||||
System.err.println("Unable to access logger factory: " + factoryName + ", using default");
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("Unable to locate logger factory class: "+factoryName+", using default");
|
||||
System.err.println("Unable to locate logger factory class: " + factoryName + ", using default");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
log = LoggerFactory.getLogger(FilterDispatcher.class);
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -273,8 +245,8 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
* @return Initialized Dispatcher
|
||||
*/
|
||||
protected Dispatcher createDispatcher(FilterConfig filterConfig) {
|
||||
Map<String,String> params = new HashMap<String,String>();
|
||||
for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements(); ) {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
for (Enumeration e = filterConfig.getInitParameterNames(); e.hasMoreElements();) {
|
||||
String name = (String) e.nextElement();
|
||||
String value = filterConfig.getInitParameter(name);
|
||||
params.put(name, value);
|
||||
@@ -283,30 +255,12 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_CONTENT setting.
|
||||
* @param val New setting
|
||||
* Modify state of StrutsConstants.STRUTS_STATIC_CONTENT_LOADER setting.
|
||||
* @param staticResourceLoader val New setting
|
||||
*/
|
||||
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_CONTENT)
|
||||
public void setServeStaticContent(String val) {
|
||||
serveStatic = "true".equals(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify state of StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE setting.
|
||||
* @param val New setting
|
||||
*/
|
||||
@Inject(StrutsConstants.STRUTS_SERVE_STATIC_BROWSER_CACHE)
|
||||
public void setServeStaticBrowserCache(String val) {
|
||||
serveStaticBrowserCache = "true".equals(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* Modify state of StrutsConstants.STRUTS_I18N_ENCODING setting.
|
||||
* @param val New setting
|
||||
*/
|
||||
@Inject(StrutsConstants.STRUTS_I18N_ENCODING)
|
||||
public void setEncoding(String val) {
|
||||
encoding = val;
|
||||
@Inject
|
||||
public void setStaticResourceLoader(StaticContentLoader staticResourceLoader) {
|
||||
this.staticResourceLoader = staticResourceLoader;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -344,7 +298,7 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
* Wrap and return the given request, if needed, so as to to transparently
|
||||
* handle multipart data as a wrapped class around the given request.
|
||||
*
|
||||
* @param request Our ServletRequest object
|
||||
* @param request Our ServletRequest object
|
||||
* @param response Our ServerResponse object
|
||||
* @return Wrapped HttpServletRequest object
|
||||
* @throws ServletException on any error
|
||||
@@ -380,31 +334,6 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a string array from a comma-delimited list of packages.
|
||||
*
|
||||
* @param packages A comma-delimited String listing packages
|
||||
* @return A string array of packages
|
||||
*/
|
||||
protected String[] parse(String packages) {
|
||||
if (packages == null) {
|
||||
return null;
|
||||
}
|
||||
List<String> pathPrefixes = new ArrayList<String>();
|
||||
|
||||
StringTokenizer st = new StringTokenizer(packages, ", \n\t");
|
||||
while (st.hasMoreTokens()) {
|
||||
String pathPrefix = st.nextToken().replace('.', '/');
|
||||
if (!pathPrefix.endsWith("/")) {
|
||||
pathPrefix += "/";
|
||||
}
|
||||
pathPrefixes.add(pathPrefix);
|
||||
}
|
||||
|
||||
return pathPrefixes.toArray(new String[pathPrefixes.size()]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Process an action or handle a request a static resource.
|
||||
* <p/>
|
||||
@@ -428,12 +357,12 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
|
||||
String timerKey = "FilterDispatcher_doFilter: ";
|
||||
try {
|
||||
|
||||
|
||||
// FIXME: this should be refactored better to not duplicate work with the action invocation
|
||||
ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
|
||||
ActionContext ctx = new ActionContext(stack.getContext());
|
||||
ActionContext.setContext(ctx);
|
||||
|
||||
|
||||
UtilTimerStack.push(timerKey);
|
||||
request = prepareDispatcherAndWrapRequest(request, response);
|
||||
ActionMapping mapping;
|
||||
@@ -453,9 +382,8 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
resourcePath = request.getPathInfo();
|
||||
}
|
||||
|
||||
if (serveStatic && resourcePath.startsWith("/struts")) {
|
||||
String name = resourcePath.substring("/struts".length());
|
||||
findStaticResource(name, request, response);
|
||||
if (staticResourceLoader.canHandle(resourcePath)) {
|
||||
staticResourceLoader.findStaticResource(resourcePath, request, response);
|
||||
} else {
|
||||
// this is a normal request, let it pass through
|
||||
chain.doFilter(request, response);
|
||||
@@ -474,137 +402,4 @@ public class FilterDispatcher implements StrutsStatics, Filter {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Locate a static resource and copy directly to the response,
|
||||
* setting the appropriate caching headers.
|
||||
*
|
||||
* @param name The resource name
|
||||
* @param request The request
|
||||
* @param response The response
|
||||
* @throws IOException If anything goes wrong
|
||||
*/
|
||||
protected void findStaticResource(String name, HttpServletRequest request, HttpServletResponse response) throws IOException {
|
||||
if (!name.endsWith(".class")) {
|
||||
for (String pathPrefix : pathPrefixes) {
|
||||
InputStream is = findInputStream(name, pathPrefix);
|
||||
if (is != null) {
|
||||
Calendar cal = Calendar.getInstance();
|
||||
|
||||
// check for if-modified-since, prior to any other headers
|
||||
long ifModifiedSince = 0;
|
||||
try {
|
||||
ifModifiedSince = request.getDateHeader("If-Modified-Since");
|
||||
} catch (Exception e) {
|
||||
log.warn("Invalid If-Modified-Since header value: '" + request.getHeader("If-Modified-Since") + "', ignoring");
|
||||
}
|
||||
long lastModifiedMillis = lastModifiedCal.getTimeInMillis();
|
||||
long now = cal.getTimeInMillis();
|
||||
cal.add(Calendar.DAY_OF_MONTH, 1);
|
||||
long expires = cal.getTimeInMillis();
|
||||
|
||||
if (ifModifiedSince > 0 && ifModifiedSince <= lastModifiedMillis) {
|
||||
// not modified, content is not sent - only basic headers and status SC_NOT_MODIFIED
|
||||
response.setDateHeader("Expires", expires);
|
||||
response.setStatus(HttpServletResponse.SC_NOT_MODIFIED);
|
||||
is.close();
|
||||
return;
|
||||
}
|
||||
|
||||
// set the content-type header
|
||||
String contentType = getContentType(name);
|
||||
if (contentType != null) {
|
||||
response.setContentType(contentType);
|
||||
}
|
||||
|
||||
if (serveStaticBrowserCache) {
|
||||
// set heading information for caching static content
|
||||
response.setDateHeader("Date", now);
|
||||
response.setDateHeader("Expires", expires);
|
||||
response.setDateHeader("Retry-After", expires);
|
||||
response.setHeader("Cache-Control", "public");
|
||||
response.setDateHeader("Last-Modified", lastModifiedMillis);
|
||||
} else {
|
||||
response.setHeader("Cache-Control", "no-cache");
|
||||
response.setHeader("Pragma", "no-cache");
|
||||
response.setHeader("Expires", "-1");
|
||||
}
|
||||
|
||||
try {
|
||||
copy(is, response.getOutputStream());
|
||||
} finally {
|
||||
is.close();
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
response.sendError(HttpServletResponse.SC_NOT_FOUND);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine the content type for the resource name.
|
||||
*
|
||||
* @param name The resource name
|
||||
* @return The mime type
|
||||
*/
|
||||
protected String getContentType(String name) {
|
||||
// NOT using the code provided activation.jar to avoid adding yet another dependency
|
||||
// this is generally OK, since these are the main files we server up
|
||||
if (name.endsWith(".js")) {
|
||||
return "text/javascript";
|
||||
} else if (name.endsWith(".css")) {
|
||||
return "text/css";
|
||||
} else if (name.endsWith(".html")) {
|
||||
return "text/html";
|
||||
} else if (name.endsWith(".txt")) {
|
||||
return "text/plain";
|
||||
} else if (name.endsWith(".gif")) {
|
||||
return "image/gif";
|
||||
} else if (name.endsWith(".jpg") || name.endsWith(".jpeg")) {
|
||||
return "image/jpeg";
|
||||
} else if (name.endsWith(".png")) {
|
||||
return "image/png";
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Copy bytes from the input stream to the output stream.
|
||||
*
|
||||
* @param input The input stream
|
||||
* @param output The output stream
|
||||
* @throws IOException If anything goes wrong
|
||||
*/
|
||||
protected void copy(InputStream input, OutputStream output) throws IOException {
|
||||
final byte[] buffer = new byte[4096];
|
||||
int n;
|
||||
while (-1 != (n = input.read(buffer))) {
|
||||
output.write(buffer, 0, n);
|
||||
}
|
||||
output.flush();
|
||||
}
|
||||
|
||||
/**
|
||||
* Look for a static resource in the classpath.
|
||||
*
|
||||
* @param name The resource name
|
||||
* @param packagePrefix The package prefix to use to locate the resource
|
||||
* @return The inputstream of the resource
|
||||
* @throws IOException If there is a problem locating the resource
|
||||
*/
|
||||
protected InputStream findInputStream(String name, String packagePrefix) throws IOException {
|
||||
String resourcePath;
|
||||
if (packagePrefix.endsWith("/") && name.startsWith("/")) {
|
||||
resourcePath = packagePrefix + name.substring(1);
|
||||
} else {
|
||||
resourcePath = packagePrefix + name;
|
||||
}
|
||||
|
||||
resourcePath = URLDecoder.decode(resourcePath, encoding);
|
||||
|
||||
return ClassLoaderUtil.getResourceAsStream(resourcePath, getClass());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,6 +47,8 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
* must "swallow" the exception. This it does by logging the
|
||||
* exception as an error.
|
||||
*
|
||||
* @deprecated Since Struts 2.1.3 as it probably isn't used anymore
|
||||
*
|
||||
*/
|
||||
public class FilterDispatcherCompatWeblogic61 extends FilterDispatcher {
|
||||
|
||||
|
||||
@@ -194,7 +194,7 @@ public class ServletActionRedirectResult extends ServletRedirectResult implement
|
||||
}
|
||||
}
|
||||
|
||||
StringBuffer tmpLocation = new StringBuffer(actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null)));
|
||||
StringBuilder tmpLocation = new StringBuilder(actionMapper.getUriFromActionMapping(new ActionMapping(actionName, namespace, method, null)));
|
||||
UrlHelper.buildParametersString(requestParameters, tmpLocation, "&");
|
||||
|
||||
setLocation(tmpLocation.toString());
|
||||
|
||||
@@ -21,12 +21,15 @@
|
||||
|
||||
package org.apache.struts2.dispatcher;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.RequestDispatcher;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.jsp.PageContext;
|
||||
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
import org.apache.struts2.views.util.UrlHelper;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
@@ -123,6 +126,17 @@ public class ServletDispatcherResult extends StrutsResultSupport {
|
||||
HttpServletResponse response = ServletActionContext.getResponse();
|
||||
RequestDispatcher dispatcher = request.getRequestDispatcher(finalLocation);
|
||||
|
||||
//add parameters passed on the location to #parameters
|
||||
// see WW-2120
|
||||
if (invocation != null && finalLocation != null && finalLocation.length() > 0
|
||||
&& finalLocation.indexOf("?") > 0) {
|
||||
String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
|
||||
Map parameters = (Map) invocation.getInvocationContext().getContextMap().get("parameters");
|
||||
Map queryParams = UrlHelper.parseQueryString(queryString, true);
|
||||
if (queryParams != null && !queryParams.isEmpty())
|
||||
parameters.putAll(queryParams);
|
||||
}
|
||||
|
||||
// if the view doesn't exist, let's do a 404
|
||||
if (dispatcher == null) {
|
||||
response.sendError(404, "result '" + finalLocation + "' not found");
|
||||
|
||||
@@ -39,12 +39,12 @@ import javax.servlet.http.HttpSession;
|
||||
* Note, this will occur lazily - only when the entry set is asked for.
|
||||
*
|
||||
*/
|
||||
public class SessionMap extends AbstractMap implements Serializable {
|
||||
public class SessionMap<K, V> extends AbstractMap<K,V> implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 4678843241638046854L;
|
||||
|
||||
protected HttpSession session;
|
||||
protected Set<Object> entries;
|
||||
protected Set<Map.Entry<K,V>> entries;
|
||||
protected HttpServletRequest request;
|
||||
|
||||
|
||||
@@ -101,23 +101,23 @@ public class SessionMap extends AbstractMap implements Serializable {
|
||||
*
|
||||
* @return a Set of attributes from the http session.
|
||||
*/
|
||||
public Set entrySet() {
|
||||
public Set<java.util.Map.Entry<K,V>> entrySet() {
|
||||
if (session == null) {
|
||||
return Collections.EMPTY_SET;
|
||||
return Collections.emptySet();
|
||||
}
|
||||
|
||||
synchronized (session) {
|
||||
if (entries == null) {
|
||||
entries = new HashSet<Object>();
|
||||
entries = new HashSet<Map.Entry<K,V>>();
|
||||
|
||||
Enumeration enumeration = session.getAttributeNames();
|
||||
Enumeration<? extends Object> enumeration = session.getAttributeNames();
|
||||
|
||||
while (enumeration.hasMoreElements()) {
|
||||
final String key = enumeration.nextElement().toString();
|
||||
final Object value = session.getAttribute(key);
|
||||
entries.add(new Map.Entry() {
|
||||
entries.add(new Map.Entry<K,V>() {
|
||||
public boolean equals(Object obj) {
|
||||
Map.Entry entry = (Map.Entry) obj;
|
||||
Map.Entry<K, V> entry = (Map.Entry<K, V>) obj;
|
||||
|
||||
return ((key == null) ? (entry.getKey() == null) : key.equals(entry.getKey())) && ((value == null) ? (entry.getValue() == null) : value.equals(entry.getValue()));
|
||||
}
|
||||
@@ -126,18 +126,18 @@ public class SessionMap extends AbstractMap implements Serializable {
|
||||
return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode());
|
||||
}
|
||||
|
||||
public Object getKey() {
|
||||
return key;
|
||||
public K getKey() {
|
||||
return (K) key;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
public V getValue() {
|
||||
return (V) value;
|
||||
}
|
||||
|
||||
public Object setValue(Object obj) {
|
||||
public V setValue(Object obj) {
|
||||
session.setAttribute(key, obj);
|
||||
|
||||
return value;
|
||||
return (V) value;
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -153,13 +153,13 @@ public class SessionMap extends AbstractMap implements Serializable {
|
||||
* @param key the name of the session attribute.
|
||||
* @return the session attribute or <tt>null</tt> if it doesn't exist.
|
||||
*/
|
||||
public Object get(Object key) {
|
||||
public V get(Object key) {
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
synchronized (session) {
|
||||
return session.getAttribute(key.toString());
|
||||
return (V) session.getAttribute(key.toString());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -170,7 +170,7 @@ public class SessionMap extends AbstractMap implements Serializable {
|
||||
* @param value the value to set.
|
||||
* @return the object that was just set.
|
||||
*/
|
||||
public Object put(Object key, Object value) {
|
||||
public V put(K key, V value) {
|
||||
synchronized (this) {
|
||||
if (session == null) {
|
||||
session = request.getSession(true);
|
||||
@@ -191,7 +191,7 @@ public class SessionMap extends AbstractMap implements Serializable {
|
||||
* @param key the name of the attribute to remove.
|
||||
* @return the value that was removed or <tt>null</tt> if the value was not found (and hence, not removed).
|
||||
*/
|
||||
public Object remove(Object key) {
|
||||
public V remove(Object key) {
|
||||
if (session == null) {
|
||||
return null;
|
||||
}
|
||||
@@ -199,10 +199,27 @@ public class SessionMap extends AbstractMap implements Serializable {
|
||||
synchronized (session) {
|
||||
entries = null;
|
||||
|
||||
Object value = get(key);
|
||||
V value = get(key);
|
||||
session.removeAttribute(key.toString());
|
||||
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the specified session attribute with the given key exists.
|
||||
*
|
||||
* @param key the name of the session attribute.
|
||||
* @return <tt>true</tt> if the session attribute exits or <tt>false</tt> if it doesn't exist.
|
||||
*/
|
||||
public boolean containsKey(Object key) {
|
||||
if (session == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
synchronized (session) {
|
||||
return (session.getAttribute(key.toString()) != null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import org.apache.struts2.dispatcher.ng.HostConfig;
|
||||
|
||||
/**
|
||||
* Interface for loading static resources, based on a path
|
||||
*/
|
||||
public interface StaticContentLoader {
|
||||
|
||||
/**
|
||||
* @param path Requested resource path
|
||||
* @return true if this loader is able to load this type of resource, false otherwise
|
||||
*/
|
||||
public boolean canHandle(String path);
|
||||
|
||||
/**
|
||||
* @param filterConfig The filter configuration
|
||||
*/
|
||||
public abstract void setHostConfig(HostConfig filterConfig);
|
||||
|
||||
/**
|
||||
* Locate a static resource and copy directly to the response, setting the
|
||||
* appropriate caching headers.
|
||||
*
|
||||
* @param path The resource name
|
||||
* @param request The request
|
||||
* @param response The response
|
||||
* @throws IOException If anything goes wrong
|
||||
*/
|
||||
public abstract void findStaticResource(String path, HttpServletRequest request, HttpServletResponse response)
|
||||
throws IOException;
|
||||
|
||||
}
|
||||
@@ -61,6 +61,8 @@ import com.opensymphony.xwork2.util.ValueStack;
|
||||
* <li><b>bufferSize</b> - the size of the buffer to copy from input to output
|
||||
* (default = <code>1024</code>).</li>
|
||||
*
|
||||
* <li><b>allowCaching</b> if set to 'false' it will set the headers 'Pragma' and 'Cache-Control'
|
||||
* to 'no-cahce', and prevent client from caching the content. (default = <code>true</code>)
|
||||
* </ul>
|
||||
*
|
||||
* <p>These parameters can also be set by exposing a similarly named getter method on your Action. For example, you can
|
||||
@@ -94,6 +96,7 @@ public class StreamResult extends StrutsResultSupport {
|
||||
protected String inputName = "inputStream";
|
||||
protected InputStream inputStream;
|
||||
protected int bufferSize = 1024;
|
||||
protected boolean allowCaching = true;
|
||||
|
||||
public StreamResult() {
|
||||
super();
|
||||
@@ -103,6 +106,24 @@ public class StreamResult extends StrutsResultSupport {
|
||||
this.inputStream = in;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the whether or not the client should be requested to allow caching of the data stream.
|
||||
*/
|
||||
public boolean getAllowCaching() {
|
||||
return allowCaching;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set allowCaching to <tt>false</tt> to indicate that the client should be requested not to cache the data stream.
|
||||
* This is set to <tt>false</tt> by default
|
||||
*
|
||||
* @param allowCaching Enable caching.
|
||||
*/
|
||||
public void setAllowCaching(boolean allowCaching) {
|
||||
this.allowCaching = allowCaching;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Returns the bufferSize.
|
||||
*/
|
||||
@@ -219,7 +240,13 @@ public class StreamResult extends StrutsResultSupport {
|
||||
|
||||
// Set the content-disposition
|
||||
if (contentDisposition != null) {
|
||||
oResponse.addHeader("Content-disposition", conditionalParse(contentDisposition, invocation));
|
||||
oResponse.addHeader("Content-Disposition", conditionalParse(contentDisposition, invocation));
|
||||
}
|
||||
|
||||
// Set the cache control headers if neccessary
|
||||
if (!allowCaching) {
|
||||
oResponse.addHeader("Pragma", "no-cache");
|
||||
oResponse.addHeader("Cache-Control", "no-cache");
|
||||
}
|
||||
|
||||
// Get the outputstream
|
||||
|
||||
@@ -400,18 +400,26 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
Configuration config = configManager.getConfiguration();
|
||||
String prefix = uri.substring(0, lastSlash);
|
||||
namespace = "";
|
||||
boolean rootAvailable = false;
|
||||
// Find the longest matching namespace, defaulting to the default
|
||||
for (Iterator i = config.getPackageConfigs().values().iterator(); i
|
||||
.hasNext();) {
|
||||
String ns = ((PackageConfig) i.next()).getNamespace();
|
||||
for (Object cfg : config.getPackageConfigs().values()) {
|
||||
String ns = ((PackageConfig) cfg).getNamespace();
|
||||
if (ns != null && prefix.startsWith(ns) && (prefix.length() == ns.length() || prefix.charAt(ns.length()) == '/')) {
|
||||
if (ns.length() > namespace.length()) {
|
||||
namespace = ns;
|
||||
}
|
||||
}
|
||||
if ("/".equals(ns)) {
|
||||
rootAvailable = true;
|
||||
}
|
||||
}
|
||||
|
||||
name = uri.substring(namespace.length() + 1);
|
||||
|
||||
// Still none found, use root namespace if found
|
||||
if (rootAvailable && "".equals(namespace)) {
|
||||
namespace = "/";
|
||||
}
|
||||
}
|
||||
|
||||
if (!allowSlashesInActionNames && name != null) {
|
||||
@@ -511,7 +519,7 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
* @see org.apache.struts2.dispatcher.mapper.ActionMapper#getUriFromActionMapping(org.apache.struts2.dispatcher.mapper.ActionMapping)
|
||||
*/
|
||||
public String getUriFromActionMapping(ActionMapping mapping) {
|
||||
StringBuffer uri = new StringBuffer();
|
||||
StringBuilder uri = new StringBuilder();
|
||||
|
||||
if (mapping.getNamespace() != null) {
|
||||
uri.append(mapping.getNamespace());
|
||||
|
||||
+21
-24
@@ -47,18 +47,19 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
/**
|
||||
* Multipart form data request adapter for Jakarta Commons Fileupload package.
|
||||
*
|
||||
*/
|
||||
public class JakartaMultiPartRequest implements MultiPartRequest {
|
||||
|
||||
static final Logger LOG = LoggerFactory.getLogger(MultiPartRequest.class);
|
||||
|
||||
// maps parameter name -> List of FileItem objects
|
||||
private Map<String,List<FileItem>> files = new HashMap<String,List<FileItem>>();
|
||||
private final Map<String,List<FileItem>> files = new HashMap<String,List<FileItem>>();
|
||||
|
||||
// maps parameter name -> List of param values
|
||||
private Map<String,List<String>> params = new HashMap<String,List<String>>();
|
||||
private final Map<String,List<String>> params = new HashMap<String,List<String>>();
|
||||
|
||||
// any errors while processing this request
|
||||
private List<String> errors = new ArrayList<String>();
|
||||
private final List<String> errors = new ArrayList<String>();
|
||||
|
||||
private long maxSize;
|
||||
|
||||
@@ -151,38 +152,36 @@ public class JakartaMultiPartRequest implements MultiPartRequest {
|
||||
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getContentType(java.lang.String)
|
||||
*/
|
||||
public String[] getContentType(String fieldName) {
|
||||
List items = (List) files.get(fieldName);
|
||||
List<FileItem> items = files.get(fieldName);
|
||||
|
||||
if (items == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> contentTypes = new ArrayList<String>(items.size());
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
FileItem fileItem = (FileItem) items.get(i);
|
||||
for (FileItem fileItem : items) {
|
||||
contentTypes.add(fileItem.getContentType());
|
||||
}
|
||||
|
||||
return (String[]) contentTypes.toArray(new String[contentTypes.size()]);
|
||||
return contentTypes.toArray(new String[contentTypes.size()]);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFile(java.lang.String)
|
||||
*/
|
||||
public File[] getFile(String fieldName) {
|
||||
List items = (List) files.get(fieldName);
|
||||
List<FileItem> items = files.get(fieldName);
|
||||
|
||||
if (items == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<File> fileList = new ArrayList<File>(items.size());
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
DiskFileItem fileItem = (DiskFileItem) items.get(i);
|
||||
fileList.add(fileItem.getStoreLocation());
|
||||
for (FileItem fileItem : items) {
|
||||
fileList.add(((DiskFileItem) fileItem).getStoreLocation());
|
||||
}
|
||||
|
||||
return (File[]) fileList.toArray(new File[fileList.size()]);
|
||||
return fileList.toArray(new File[fileList.size()]);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -196,40 +195,38 @@ public class JakartaMultiPartRequest implements MultiPartRequest {
|
||||
}
|
||||
|
||||
List<String> fileNames = new ArrayList<String>(items.size());
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
DiskFileItem fileItem = (DiskFileItem) items.get(i);
|
||||
for (FileItem fileItem : items) {
|
||||
fileNames.add(getCanonicalName(fileItem.getName()));
|
||||
}
|
||||
|
||||
return (String[]) fileNames.toArray(new String[fileNames.size()]);
|
||||
return fileNames.toArray(new String[fileNames.size()]);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getFilesystemName(java.lang.String)
|
||||
*/
|
||||
public String[] getFilesystemName(String fieldName) {
|
||||
List items = (List) files.get(fieldName);
|
||||
List<FileItem> items = files.get(fieldName);
|
||||
|
||||
if (items == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
List<String> fileNames = new ArrayList<String>(items.size());
|
||||
for (int i = 0; i < items.size(); i++) {
|
||||
DiskFileItem fileItem = (DiskFileItem) items.get(i);
|
||||
fileNames.add(fileItem.getStoreLocation().getName());
|
||||
for (FileItem fileItem : items) {
|
||||
fileNames.add(((DiskFileItem) fileItem).getStoreLocation().getName());
|
||||
}
|
||||
|
||||
return (String[]) fileNames.toArray(new String[fileNames.size()]);
|
||||
return fileNames.toArray(new String[fileNames.size()]);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.apache.struts2.dispatcher.multipart.MultiPartRequest#getParameter(java.lang.String)
|
||||
*/
|
||||
public String getParameter(String name) {
|
||||
List v = (List) params.get(name);
|
||||
List<String> v = params.get(name);
|
||||
if (v != null && v.size() > 0) {
|
||||
return (String) v.get(0);
|
||||
return v.get(0);
|
||||
}
|
||||
|
||||
return null;
|
||||
@@ -248,7 +245,7 @@ public class JakartaMultiPartRequest implements MultiPartRequest {
|
||||
public String[] getParameterValues(String name) {
|
||||
List<String> v = params.get(name);
|
||||
if (v != null && v.size() > 0) {
|
||||
return (String[]) v.toArray(new String[v.size()]);
|
||||
return v.toArray(new String[v.size()]);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng;
|
||||
|
||||
import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.StaticContentLoader;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
import org.apache.struts2.RequestUtils;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Contains execution operations for filters
|
||||
*/
|
||||
public class ExecuteOperations {
|
||||
private ServletContext servletContext;
|
||||
private Dispatcher dispatcher;
|
||||
|
||||
public ExecuteOperations(ServletContext servletContext, Dispatcher dispatcher) {
|
||||
this.dispatcher = dispatcher;
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to execute a request for a static resource
|
||||
* @return True if it was handled, false if the filter should fall through
|
||||
* @throws IOException
|
||||
* @throws ServletException
|
||||
*/
|
||||
public boolean executeStaticResourceRequest(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
// there is no action in this request, should we look for a static resource?
|
||||
String resourcePath = RequestUtils.getServletPath(request);
|
||||
|
||||
if ("".equals(resourcePath) && null != request.getPathInfo()) {
|
||||
resourcePath = request.getPathInfo();
|
||||
}
|
||||
|
||||
StaticContentLoader staticResourceLoader = dispatcher.getContainer().getInstance(StaticContentLoader.class);
|
||||
if (staticResourceLoader.canHandle(resourcePath)) {
|
||||
staticResourceLoader.findStaticResource(resourcePath, request, response);
|
||||
// The framework did its job here
|
||||
return true;
|
||||
|
||||
} else {
|
||||
// this is a normal request, let it pass through
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes an action
|
||||
* @throws ServletException
|
||||
*/
|
||||
public void executeAction(HttpServletRequest request, HttpServletResponse response, ActionMapping mapping) throws ServletException {
|
||||
dispatcher.serviceAction(request, response, servletContext, mapping);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Abstraction for host configuration information such as init params or the servlet context.
|
||||
*/
|
||||
public interface HostConfig {
|
||||
|
||||
/**
|
||||
* @param key The parameter key
|
||||
* @return The parameter value
|
||||
*/
|
||||
String getInitParameter(String key);
|
||||
|
||||
/**
|
||||
* @return A list of parameter names
|
||||
*/
|
||||
Iterator<String> getInitParameterNames();
|
||||
|
||||
/**
|
||||
* @return The servlet context
|
||||
*/
|
||||
ServletContext getServletContext();
|
||||
}
|
||||
@@ -0,0 +1,110 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng;
|
||||
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.StaticContentLoader;
|
||||
import org.apache.struts2.util.ClassLoaderUtils;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Iterator;
|
||||
|
||||
/**
|
||||
* Contains initialization operations
|
||||
*/
|
||||
public class InitOperations {
|
||||
|
||||
public InitOperations() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the internal Struts logging
|
||||
*/
|
||||
public void initLogging(HostConfig filterConfig) {
|
||||
String factoryName = filterConfig.getInitParameter("loggerFactory");
|
||||
if (factoryName != null) {
|
||||
try {
|
||||
Class cls = ClassLoaderUtils.loadClass(factoryName, this.getClass());
|
||||
LoggerFactory fac = (LoggerFactory) cls.newInstance();
|
||||
LoggerFactory.setLoggerFactory(fac);
|
||||
} catch (InstantiationException e) {
|
||||
System.err.println("Unable to instantiate logger factory: " + factoryName + ", using default");
|
||||
e.printStackTrace();
|
||||
} catch (IllegalAccessException e) {
|
||||
System.err.println("Unable to access logger factory: " + factoryName + ", using default");
|
||||
e.printStackTrace();
|
||||
} catch (ClassNotFoundException e) {
|
||||
System.err.println("Unable to locate logger factory class: " + factoryName + ", using default");
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and initializes the dispatcher
|
||||
*/
|
||||
public Dispatcher initDispatcher(HostConfig filterConfig) {
|
||||
Dispatcher dispatcher = createDispatcher(filterConfig);
|
||||
dispatcher.init();
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Initializes the static content loader with the filter configuration
|
||||
*/
|
||||
public StaticContentLoader initStaticContentLoader(HostConfig filterConfig, Dispatcher dispatcher) {
|
||||
StaticContentLoader loader = dispatcher.getContainer().getInstance(StaticContentLoader.class);
|
||||
loader.setHostConfig(filterConfig);
|
||||
return loader;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The dispatcher on the thread.
|
||||
* @throws IllegalStateException If there is no dispatcher available
|
||||
*/
|
||||
public Dispatcher findDispatcherOnThread() {
|
||||
Dispatcher dispatcher = Dispatcher.getInstance();
|
||||
if (dispatcher == null) {
|
||||
throw new IllegalStateException("Must have the StrutsPrepareFilter execute before this one");
|
||||
}
|
||||
return dispatcher;
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a {@link Dispatcher}
|
||||
*/
|
||||
private Dispatcher createDispatcher(HostConfig filterConfig) {
|
||||
Map<String, String> params = new HashMap<String, String>();
|
||||
for (Iterator e = filterConfig.getInitParameterNames(); e.hasNext();) {
|
||||
String name = (String) e.next();
|
||||
String value = filterConfig.getInitParameter(name);
|
||||
params.put(name, value);
|
||||
}
|
||||
return new Dispatcher(filterConfig.getServletContext(), params);
|
||||
}
|
||||
|
||||
public void cleanup() {
|
||||
ActionContext.setContext(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,171 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng;
|
||||
|
||||
import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapper;
|
||||
import org.apache.struts2.StrutsException;
|
||||
|
||||
import javax.servlet.ServletException;
|
||||
import javax.servlet.ServletContext;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
|
||||
/**
|
||||
* Contains preparation operations for a request before execution
|
||||
*/
|
||||
public class PrepareOperations {
|
||||
|
||||
private ServletContext servletContext;
|
||||
private Dispatcher dispatcher;
|
||||
private static final String STRUTS_ACTION_MAPPING_KEY = "struts.actionMapping";
|
||||
public static final String CLEANUP_RECURSION_COUNTER = "__cleanup_recursion_counter";
|
||||
private Logger log = LoggerFactory.getLogger(PrepareOperations.class);
|
||||
|
||||
public PrepareOperations(ServletContext servletContext, Dispatcher dispatcher) {
|
||||
this.dispatcher = dispatcher;
|
||||
this.servletContext = servletContext;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the action context and initializes the thread local
|
||||
*/
|
||||
public ActionContext createActionContext(HttpServletRequest request, HttpServletResponse response) {
|
||||
ActionContext ctx;
|
||||
Integer counter = 1;
|
||||
Integer oldCounter = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);
|
||||
if (oldCounter != null) {
|
||||
counter = oldCounter + 1;
|
||||
}
|
||||
|
||||
ActionContext oldContext = ActionContext.getContext();
|
||||
if (oldContext != null) {
|
||||
// detected existing context, so we are probably in a forward
|
||||
ctx = new ActionContext(new HashMap<String, Object>(oldContext.getContextMap()));
|
||||
} else {
|
||||
ValueStack stack = dispatcher.getContainer().getInstance(ValueStackFactory.class).createValueStack();
|
||||
stack.getContext().putAll(dispatcher.createContextMap(request, response, null, servletContext));
|
||||
ctx = new ActionContext(stack.getContext());
|
||||
}
|
||||
request.setAttribute(CLEANUP_RECURSION_COUNTER, counter);
|
||||
ActionContext.setContext(ctx);
|
||||
return ctx;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up a request of thread locals
|
||||
*/
|
||||
public void cleanupRequest(HttpServletRequest request) {
|
||||
Integer counterVal = (Integer) request.getAttribute(CLEANUP_RECURSION_COUNTER);
|
||||
if (counterVal != null) {
|
||||
counterVal -= 1;
|
||||
request.setAttribute(CLEANUP_RECURSION_COUNTER, counterVal);
|
||||
if (counterVal > 0 ) {
|
||||
if (log.isDebugEnabled()) {
|
||||
log.debug("skipping cleanup counter="+counterVal);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// always clean up the thread request, even if an action hasn't been executed
|
||||
ActionContext.setContext(null);
|
||||
Dispatcher.setInstance(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the dispatcher to the dispatcher thread local
|
||||
*/
|
||||
public void assignDispatcherToThread() {
|
||||
Dispatcher.setInstance(dispatcher);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the request encoding and locale on the response
|
||||
*/
|
||||
public void setEncodingAndLocale(HttpServletRequest request, HttpServletResponse response) {
|
||||
dispatcher.prepare(request, response);
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the request with the Struts wrapper that handles multipart requests better
|
||||
* @return The new request, if there is one
|
||||
* @throws ServletException
|
||||
*/
|
||||
public HttpServletRequest wrapRequest(HttpServletRequest oldRequest) throws ServletException {
|
||||
HttpServletRequest request = oldRequest;
|
||||
try {
|
||||
// Wrap request first, just in case it is multipart/form-data
|
||||
// parameters might not be accessible through before encoding (ww-1278)
|
||||
request = dispatcher.wrapRequest(request, servletContext);
|
||||
} catch (IOException e) {
|
||||
String message = "Could not wrap servlet request with MultipartRequestWrapper!";
|
||||
throw new ServletException(message, e);
|
||||
}
|
||||
return request;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds and optionally creates an {@link ActionMapping}. It first looks in the current request to see if one
|
||||
* has already been found, otherwise, it creates it and stores it in the request. No mapping will be created in the
|
||||
* case of static resource requests or unidentifiable requests for other servlets, for example.
|
||||
*/
|
||||
public ActionMapping findActionMapping(HttpServletRequest request, HttpServletResponse response) {
|
||||
ActionMapping mapping = (ActionMapping) request.getAttribute(STRUTS_ACTION_MAPPING_KEY);
|
||||
if (mapping == null) {
|
||||
try {
|
||||
mapping = dispatcher.getContainer().getInstance(ActionMapper.class).getMapping(request, dispatcher.getConfigurationManager());
|
||||
if (mapping != null) {
|
||||
request.setAttribute(STRUTS_ACTION_MAPPING_KEY, mapping);
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
dispatcher.sendError(request, response, servletContext, HttpServletResponse.SC_INTERNAL_SERVER_ERROR, ex);
|
||||
}
|
||||
}
|
||||
|
||||
return mapping;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleans up the dispatcher instance
|
||||
*/
|
||||
public void cleanupDispatcher() {
|
||||
if (dispatcher == null) {
|
||||
throw new StrutsException("something is seriously wrong, Dispatcher is not initialized (null) ");
|
||||
} else {
|
||||
try {
|
||||
dispatcher.cleanup();
|
||||
} finally {
|
||||
ActionContext.setContext(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng.filter;
|
||||
|
||||
import org.apache.struts2.util.MakeIterator;
|
||||
|
||||
import javax.servlet.FilterConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.struts2.dispatcher.ng.HostConfig;
|
||||
|
||||
/**
|
||||
* Host configuration that wraps FilterConfig
|
||||
*/
|
||||
public class FilterHostConfig implements HostConfig {
|
||||
|
||||
private FilterConfig config;
|
||||
|
||||
public FilterHostConfig(FilterConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
public String getInitParameter(String key) {
|
||||
return config.getInitParameter(key);
|
||||
}
|
||||
|
||||
public Iterator<String> getInitParameterNames() {
|
||||
return MakeIterator.convert(config.getInitParameterNames());
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return config.getServletContext();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng.filter;
|
||||
|
||||
import org.apache.struts2.StrutsStatics;
|
||||
import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.ng.PrepareOperations;
|
||||
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
|
||||
import org.apache.struts2.dispatcher.ng.InitOperations;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Executes the discovered request information. This filter requires the {@link StrutsPrepareFilter} to have already
|
||||
* been executed in the current chain.
|
||||
*/
|
||||
public class StrutsExecuteFilter implements StrutsStatics, Filter {
|
||||
private PrepareOperations prepare;
|
||||
private ExecuteOperations execute;
|
||||
|
||||
private FilterConfig filterConfig;
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
this.filterConfig = filterConfig;
|
||||
}
|
||||
|
||||
protected synchronized void lazyInit() {
|
||||
if (execute == null) {
|
||||
InitOperations init = new InitOperations();
|
||||
Dispatcher dispatcher = init.findDispatcherOnThread();
|
||||
init.initStaticContentLoader(new FilterHostConfig(filterConfig), dispatcher);
|
||||
|
||||
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
|
||||
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
|
||||
// This is necessary since we need the dispatcher instance, which was created by the prepare filter
|
||||
lazyInit();
|
||||
|
||||
ActionMapping mapping = prepare.findActionMapping(request, response);
|
||||
if (mapping == null) {
|
||||
boolean handled = execute.executeStaticResourceRequest(request, response);
|
||||
if (!handled) {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
} else {
|
||||
execute.executeAction(request, response, mapping);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
prepare = null;
|
||||
execute = null;
|
||||
filterConfig = null;
|
||||
}
|
||||
}
|
||||
+86
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng.filter;
|
||||
|
||||
import org.apache.struts2.StrutsStatics;
|
||||
import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.ng.PrepareOperations;
|
||||
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
|
||||
import org.apache.struts2.dispatcher.ng.InitOperations;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Handles both the preparation and execution phases of the Struts dispatching process. This filter is better to use
|
||||
* when you don't have another filter that needs access to action context information, such as Sitemesh.
|
||||
*/
|
||||
public class StrutsPrepareAndExecuteFilter implements StrutsStatics, Filter {
|
||||
private PrepareOperations prepare;
|
||||
private ExecuteOperations execute;
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
InitOperations init = new InitOperations();
|
||||
try {
|
||||
FilterHostConfig config = new FilterHostConfig(filterConfig);
|
||||
init.initLogging(config);
|
||||
Dispatcher dispatcher = init.initDispatcher(config);
|
||||
init.initStaticContentLoader(config, dispatcher);
|
||||
|
||||
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
|
||||
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
|
||||
} finally {
|
||||
init.cleanup();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
|
||||
try {
|
||||
prepare.createActionContext(request, response);
|
||||
prepare.assignDispatcherToThread();
|
||||
prepare.setEncodingAndLocale(request, response);
|
||||
request = prepare.wrapRequest(request);
|
||||
ActionMapping mapping = prepare.findActionMapping(request, response);
|
||||
if (mapping == null) {
|
||||
boolean handled = execute.executeStaticResourceRequest(request, response);
|
||||
if (!handled) {
|
||||
chain.doFilter(request, response);
|
||||
}
|
||||
} else {
|
||||
execute.executeAction(request, response, mapping);
|
||||
}
|
||||
} finally {
|
||||
prepare.cleanupRequest(request);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
prepare.cleanupDispatcher();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng.filter;
|
||||
|
||||
import org.apache.struts2.StrutsStatics;
|
||||
import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.ng.PrepareOperations;
|
||||
import org.apache.struts2.dispatcher.ng.InitOperations;
|
||||
|
||||
import javax.servlet.*;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Prepares the request for execution by a later {@link org.apache.struts2.dispatcher.ng.filter.StrutsExecuteFilter} filter instance.
|
||||
*/
|
||||
public class StrutsPrepareFilter implements StrutsStatics, Filter {
|
||||
private PrepareOperations prepare;
|
||||
|
||||
public void init(FilterConfig filterConfig) throws ServletException {
|
||||
InitOperations init = new InitOperations();
|
||||
try {
|
||||
FilterHostConfig config = new FilterHostConfig(filterConfig);
|
||||
init.initLogging(config);
|
||||
Dispatcher dispatcher = init.initDispatcher(config);
|
||||
|
||||
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
|
||||
} finally {
|
||||
init.cleanup();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException {
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) req;
|
||||
HttpServletResponse response = (HttpServletResponse) res;
|
||||
|
||||
try {
|
||||
prepare.createActionContext(request, response);
|
||||
prepare.assignDispatcherToThread();
|
||||
prepare.setEncodingAndLocale(request, response);
|
||||
request = prepare.wrapRequest(request);
|
||||
prepare.findActionMapping(request, response);
|
||||
|
||||
chain.doFilter(request, response);
|
||||
} finally {
|
||||
prepare.cleanupRequest(request);
|
||||
}
|
||||
}
|
||||
|
||||
public void destroy() {
|
||||
prepare.cleanupDispatcher();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
/**
|
||||
* This package contains a reimagining of the traditional Struts filter dispatchers. Each specific deployment has
|
||||
* their own filters to prevent confusion. In addition, the operations have been explicitly pulled into *Operations
|
||||
* objects that try to document through method naming what is happening at every step. Here are a few common use
|
||||
* cases and how you would manage the Struts deployment:
|
||||
*
|
||||
* <h3>Simple Dispatcher</h3>
|
||||
* <pre>
|
||||
* <filter>
|
||||
* <filter-name>struts2</filter-name>
|
||||
* <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter</filter-class>
|
||||
* </filter>
|
||||
*
|
||||
* <filter-mapping>
|
||||
* <filter-name>struts2</filter-name>
|
||||
* <url-pattern>/*</url-pattern>
|
||||
* </filter-mapping>
|
||||
* </pre>
|
||||
*
|
||||
* <h3>Deployment with Sitemesh</h3>
|
||||
* <pre>
|
||||
* <filter>
|
||||
* <filter-name>struts2-prepare</filter-name>
|
||||
* <filter-class>org.apache.struts2.dispatcher.filter.StrutsPrepareFilter</filter-class>
|
||||
* </filter>
|
||||
* <filter>
|
||||
* <filter-name>sitemesh</filter-name>
|
||||
* <filter-class>com.opensymphony.module.sitemesh.filter.PageFilter</filter-class>
|
||||
* </filter>
|
||||
* <filter>
|
||||
* <filter-name>struts2-execute</filter-name>
|
||||
* <filter-class>org.apache.struts2.dispatcher.filter.StrutsExecuteFilter</filter-class>
|
||||
* </filter>
|
||||
*
|
||||
* <filter-mapping>
|
||||
* <filter-name>struts2-prepare</filter-name>
|
||||
* <url-pattern>/*</url-pattern>
|
||||
* </filter-mapping>
|
||||
* <filter-mapping>
|
||||
* <filter-name>sitemesh</filter-name>
|
||||
* <url-pattern>/*</url-pattern>
|
||||
* </filter-mapping>
|
||||
* <filter-mapping>
|
||||
* <filter-name>struts2-execute</filter-name>
|
||||
* <url-pattern>/*</url-pattern>
|
||||
* </filter-mapping>
|
||||
* </pre>
|
||||
*
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng;
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng.servlet;
|
||||
|
||||
import org.apache.struts2.util.MakeIterator;
|
||||
|
||||
import javax.servlet.ServletConfig;
|
||||
import javax.servlet.ServletContext;
|
||||
import java.util.Iterator;
|
||||
|
||||
import org.apache.struts2.dispatcher.ng.HostConfig;
|
||||
|
||||
/**
|
||||
* Host configuration that wraps a ServletConfig
|
||||
*/
|
||||
public class ServletHostConfig implements HostConfig {
|
||||
private ServletConfig config;
|
||||
|
||||
public ServletHostConfig(ServletConfig config) {
|
||||
this.config = config;
|
||||
}
|
||||
public String getInitParameter(String key) {
|
||||
return config.getInitParameter(key);
|
||||
}
|
||||
|
||||
public Iterator<String> getInitParameterNames() {
|
||||
return MakeIterator.convert(config.getInitParameterNames());
|
||||
}
|
||||
|
||||
public ServletContext getServletContext() {
|
||||
return config.getServletContext();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
/*
|
||||
* $Id: DefaultActionSupport.java 651946 2008-04-27 13:41:38Z apetrelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.dispatcher.ng.servlet;
|
||||
|
||||
import org.apache.struts2.dispatcher.Dispatcher;
|
||||
import org.apache.struts2.dispatcher.ng.InitOperations;
|
||||
import org.apache.struts2.dispatcher.ng.PrepareOperations;
|
||||
import org.apache.struts2.dispatcher.ng.ExecuteOperations;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
|
||||
import javax.servlet.http.HttpServlet;
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
import javax.servlet.http.HttpServletResponse;
|
||||
import javax.servlet.*;
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* Servlet dispatcher for Struts. The preferred way to use Struts is as a filter via the
|
||||
* {@link org.apache.struts2.dispatcher.ng.filter.StrutsPrepareAndExecuteFilter} and its variants. This servlet dispatcher
|
||||
* is only for those that really know what they are doing as it may not support every feature of Struts, particularly
|
||||
* static resource serving.
|
||||
*/
|
||||
public class StrutsServlet extends HttpServlet {
|
||||
|
||||
private PrepareOperations prepare;
|
||||
private ExecuteOperations execute;
|
||||
|
||||
@Override
|
||||
public void init(ServletConfig filterConfig) throws ServletException {
|
||||
InitOperations init = new InitOperations();
|
||||
try {
|
||||
ServletHostConfig config = new ServletHostConfig(filterConfig);
|
||||
init.initLogging(config);
|
||||
Dispatcher dispatcher = init.initDispatcher(config);
|
||||
init.initStaticContentLoader(config, dispatcher);
|
||||
|
||||
prepare = new PrepareOperations(filterConfig.getServletContext(), dispatcher);
|
||||
execute = new ExecuteOperations(filterConfig.getServletContext(), dispatcher);
|
||||
} finally {
|
||||
init.cleanup();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void service(HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException {
|
||||
|
||||
try {
|
||||
prepare.createActionContext(request, response);
|
||||
prepare.assignDispatcherToThread();
|
||||
prepare.setEncodingAndLocale(request, response);
|
||||
request = prepare.wrapRequest(request);
|
||||
ActionMapping mapping = prepare.findActionMapping(request, response);
|
||||
if (mapping == null) {
|
||||
boolean handled = execute.executeStaticResourceRequest(request, response);
|
||||
if (!handled)
|
||||
throw new ServletException("Resource loading not supported, use the StrutsPrepareAndExecuteFilter instead.");
|
||||
} else {
|
||||
execute.executeAction(request, response, mapping);
|
||||
}
|
||||
} finally {
|
||||
prepare.cleanupRequest(request);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void destroy() {
|
||||
prepare.cleanupDispatcher();
|
||||
}
|
||||
}
|
||||
@@ -85,21 +85,4 @@ public class StrutsObjectFactory extends ObjectFactory {
|
||||
}
|
||||
}
|
||||
|
||||
public Result buildResult(ResultConfig resultConfig, Map extraContext) throws Exception {
|
||||
String resultClassName = resultConfig.getClassName();
|
||||
if (resultClassName == null)
|
||||
return null;
|
||||
|
||||
Object result = buildBean(resultClassName, extraContext);
|
||||
reflectionProvider.setProperties(resultConfig.getParams(), result, extraContext);
|
||||
|
||||
if (result instanceof Result)
|
||||
return (Result) result;
|
||||
|
||||
// This is for the new API:
|
||||
// if (result instanceof org.apache.struts2.spi.Result)
|
||||
// return new ResultAdapter((org.apache.struts2.spi.Result) result);
|
||||
|
||||
throw new ConfigurationException(result.getClass().getName() + " does not implement Result.");
|
||||
}
|
||||
}
|
||||
|
||||
+39
-14
@@ -26,6 +26,7 @@ import com.opensymphony.xwork2.ActionContext;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Collections;
|
||||
import java.util.TreeMap;
|
||||
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
@@ -36,31 +37,31 @@ import org.apache.struts2.dispatcher.mapper.ActionMapping;
|
||||
* exactly like {@link ParametersInterceptor}, only the parameters come from the {@link ActionMapping}, not the
|
||||
* {@link ActionContext#getParameters()} method.
|
||||
* <!-- END SNIPPET: description -->
|
||||
*
|
||||
* <p/>
|
||||
* <p/> <u>Interceptor parameters:</u>
|
||||
*
|
||||
* <p/>
|
||||
* <!-- START SNIPPET: parameters -->
|
||||
*
|
||||
* <p/>
|
||||
* <ul>
|
||||
*
|
||||
* <p/>
|
||||
* <li>ordered - set to true if you want the top-down property setter behaviour</li>
|
||||
*
|
||||
* <p/>
|
||||
* </ul>
|
||||
*
|
||||
* <p/>
|
||||
* <!-- END SNIPPET: parameters -->
|
||||
*
|
||||
* <p/>
|
||||
* <p/> <u>Extending the interceptor:</u>
|
||||
*
|
||||
* <p/>
|
||||
* <!-- START SNIPPET: extending -->
|
||||
*
|
||||
* <p/>
|
||||
* <p/> The best way to add behavior to this interceptor is to utilize the {@link com.opensymphony.xwork2.interceptor.ParameterNameAware} interface in your
|
||||
* actions. However, if you wish to apply a global rule that isn't implemented in your action, then you could extend
|
||||
* this interceptor and override the {@link #acceptableName(String)} method.
|
||||
*
|
||||
* <p/>
|
||||
* <!-- END SNIPPET: extending -->
|
||||
*
|
||||
* <p/>
|
||||
* <p/> <u>Example code:</u>
|
||||
*
|
||||
* <p/>
|
||||
* <pre>
|
||||
* <!-- START SNIPPET: example -->
|
||||
* <action name="someAction" class="com.examples.SomeAction">
|
||||
@@ -75,9 +76,10 @@ public class ActionMappingParametersInteceptor extends ParametersInterceptor {
|
||||
/**
|
||||
* @param ac The action context
|
||||
* @return the parameters from the action mapping in the context. If none found, returns
|
||||
* an empty map.
|
||||
* an empty map.
|
||||
*/
|
||||
protected Map retrieveParametersFromContext(ActionContext ac) {
|
||||
@Override
|
||||
protected Map retrieveParameters(ActionContext ac) {
|
||||
ActionMapping mapping = (ActionMapping) ac.get(ServletActionContext.ACTION_MAPPING);
|
||||
if (mapping != null) {
|
||||
return mapping.getParams();
|
||||
@@ -85,4 +87,27 @@ public class ActionMappingParametersInteceptor extends ParametersInterceptor {
|
||||
return Collections.EMPTY_MAP;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the parameters into context's ParameterMap
|
||||
*
|
||||
* @param ac The action context
|
||||
* @param newParams The parameter map to apply
|
||||
* <p/>
|
||||
* In this class this is a no-op, since the parameters were fetched from the same location.
|
||||
* In subclasses both retrieveParameters() and addParametersToContext() should be overridden.
|
||||
*/
|
||||
@Override
|
||||
protected void addParametersToContext(ActionContext ac, Map newParams) {
|
||||
Map previousParams = ac.getParameters();
|
||||
Map combinedParams = null;
|
||||
if (previousParams != null) {
|
||||
combinedParams = new TreeMap(previousParams);
|
||||
} else {
|
||||
combinedParams = new TreeMap();
|
||||
}
|
||||
combinedParams.putAll(newParams);
|
||||
|
||||
ac.setParameters(combinedParams);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
package org.apache.struts2.interceptor;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
import com.opensymphony.xwork2.interceptor.Interceptor;
|
||||
|
||||
import java.util.Map;
|
||||
@@ -53,6 +55,8 @@ public class CheckboxInterceptor implements Interceptor {
|
||||
|
||||
private String uncheckedValue = Boolean.FALSE.toString();
|
||||
|
||||
private static final Logger LOG = LoggerFactory.getLogger(CheckboxInterceptor.class);
|
||||
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
@@ -61,7 +65,7 @@ public class CheckboxInterceptor implements Interceptor {
|
||||
|
||||
public String intercept(ActionInvocation ai) throws Exception {
|
||||
Map parameters = ai.getInvocationContext().getParameters();
|
||||
Map<String, String> newParams = new HashMap<String, String>();
|
||||
Map<String, String[]> newParams = new HashMap<String, String[]>();
|
||||
Set<String> keys = parameters.keySet();
|
||||
for (Iterator<String> iterator = keys.iterator(); iterator.hasNext();) {
|
||||
String key = iterator.next();
|
||||
@@ -69,12 +73,17 @@ public class CheckboxInterceptor implements Interceptor {
|
||||
if (key.startsWith("__checkbox_")) {
|
||||
String name = key.substring("__checkbox_".length());
|
||||
|
||||
Object values = parameters.get(key);
|
||||
iterator.remove();
|
||||
if (values != null && values instanceof String[] && ((String[])values).length > 1) {
|
||||
LOG.debug("Bypassing automatic checkbox detection due to multiple checkboxes of the same name: #1", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
// is this checkbox checked/submitted?
|
||||
if (!parameters.containsKey(name)) {
|
||||
// if not, let's be sure to default the value to false
|
||||
newParams.put(name, uncheckedValue);
|
||||
newParams.put(name, new String[]{uncheckedValue});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,9 @@ import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
import org.apache.struts2.util.TokenHelper;
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
|
||||
/**
|
||||
@@ -212,6 +215,7 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor {
|
||||
String name = getBackgroundProcessName(proxy);
|
||||
ActionContext context = actionInvocation.getInvocationContext();
|
||||
Map session = context.getSession();
|
||||
HttpSession httpSession = ServletActionContext.getRequest().getSession(true);
|
||||
|
||||
Boolean secondTime = true;
|
||||
if (executeAfterValidationPass) {
|
||||
@@ -225,7 +229,9 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
synchronized (session) {
|
||||
//sync on the real HttpSession as the session from the context is a wrap that is created
|
||||
//on every request
|
||||
synchronized (httpSession) {
|
||||
BackgroundProcess bp = (BackgroundProcess) session.get(KEY + name);
|
||||
|
||||
if ((!executeAfterValidationPass || secondTime) && bp == null) {
|
||||
|
||||
@@ -22,15 +22,7 @@
|
||||
package org.apache.struts2.interceptor;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Enumeration;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.Locale;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.StringTokenizer;
|
||||
import java.util.*;
|
||||
|
||||
import javax.servlet.http.HttpServletRequest;
|
||||
|
||||
@@ -43,133 +35,170 @@ import com.opensymphony.xwork2.ActionProxy;
|
||||
import com.opensymphony.xwork2.ValidationAware;
|
||||
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
|
||||
import com.opensymphony.xwork2.util.LocalizedTextUtil;
|
||||
import com.opensymphony.xwork2.util.TextParseUtil;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: description -->
|
||||
*
|
||||
* <p/>
|
||||
* Interceptor that is based off of {@link MultiPartRequestWrapper}, which is automatically applied for any request that
|
||||
* includes a file. It adds the following parameters, where [File Name] is the name given to the file uploaded by the
|
||||
* HTML form:
|
||||
*
|
||||
* <p/>
|
||||
* <ul>
|
||||
*
|
||||
* <p/>
|
||||
* <li>[File Name] : File - the actual File</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li>[File Name]ContentType : String - the content type of the file</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li>[File Name]FileName : String - the actual name of the file uploaded (not the HTML name)</li>
|
||||
*
|
||||
* <p/>
|
||||
* </ul>
|
||||
*
|
||||
* <p/>
|
||||
* <p/> You can get access to these files by merely providing setters in your action that correspond to any of the three
|
||||
* patterns above, such as setDocument(File document), setDocumentContentType(String contentType), etc.
|
||||
* <br/>See the example code section.
|
||||
*
|
||||
* <p/>
|
||||
* <p/> This interceptor will add several field errors, assuming that the action implements {@link ValidationAware}.
|
||||
* These error messages are based on several i18n values stored in struts-messages.properties, a default i18n file
|
||||
* processed for all i18n requests. You can override the text of these messages by providing text for the following
|
||||
* keys:
|
||||
*
|
||||
* <p/>
|
||||
* <ul>
|
||||
*
|
||||
* <p/>
|
||||
* <li>struts.messages.error.uploading - a general error that occurs when the file could not be uploaded</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li>struts.messages.error.file.too.large - occurs when the uploaded file is too large</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li>struts.messages.error.content.type.not.allowed - occurs when the uploaded file does not match the expected
|
||||
* content types specified</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li>struts.messages.error.file.extension.not.allowed - occurs when the uploaded file does not match the expected
|
||||
* file extensions specified</li>
|
||||
* <p/>
|
||||
* </ul>
|
||||
*
|
||||
* <p/>
|
||||
* <!-- END SNIPPET: description -->
|
||||
*
|
||||
* <p/>
|
||||
* <p/> <u>Interceptor parameters:</u>
|
||||
*
|
||||
* <p/>
|
||||
* <!-- START SNIPPET: parameters -->
|
||||
*
|
||||
* <p/>
|
||||
* <ul>
|
||||
*
|
||||
* <p/>
|
||||
* <li>maximumSize (optional) - the maximum size (in bytes) that the interceptor will allow a file reference to be set
|
||||
* on the action. Note, this is <b>not</b> related to the various properties found in struts.properties.
|
||||
* Default to approximately 2MB.</li>
|
||||
*
|
||||
* <p/>
|
||||
* <li>allowedTypes (optional) - a comma separated list of content types (ie: text/html) that the interceptor will allow
|
||||
* a file reference to be set on the action. If none is specified allow all types to be uploaded.</li>
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <!-- END SNIPPET: parameters -->
|
||||
*
|
||||
* <p/> <u>Extending the interceptor:</u>
|
||||
*
|
||||
* <p/>
|
||||
*
|
||||
* <li>allowedExtensions (optional) - a comma separated list of file extensions (ie: .html) that the interceptor will allow
|
||||
* a file reference to be set on the action. If none is specified allow all extensions to be uploaded.</li>
|
||||
* </ul>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <!-- END SNIPPET: parameters -->
|
||||
* <p/>
|
||||
* <p/> <u>Extending the interceptor:</u>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <p/>
|
||||
* <!-- START SNIPPET: extending -->
|
||||
*
|
||||
* You can extend this interceptor and override the {@link #acceptFile} method to provide more control over which files
|
||||
* <p/>
|
||||
* You can extend this interceptor and override the acceptFile method to provide more control over which files
|
||||
* are supported and which are not.
|
||||
*
|
||||
* <p/>
|
||||
* <!-- END SNIPPET: extending -->
|
||||
*
|
||||
* <p/>
|
||||
* <p/> <u>Example code:</u>
|
||||
*
|
||||
* <p/>
|
||||
* <pre>
|
||||
* <!-- START SNIPPET: example -->
|
||||
* <action name="doUpload" class="com.examples.UploadAction">
|
||||
* <!-- START SNIPPET: example-configuration -->
|
||||
* <action name="doUpload" class="com.example.UploadAction">
|
||||
* <interceptor-ref name="fileUpload"/>
|
||||
* <interceptor-ref name="basicStack"/>
|
||||
* <result name="success">good_result.ftl</result>
|
||||
* <result name="success">good_result.jsp</result>
|
||||
* </action>
|
||||
* <!-- END SNIPPET: example-configuration -->
|
||||
* </pre>
|
||||
*
|
||||
* And then you need to set encoding <code>multipart/form-data</code> in the form where the user selects the file to upload.
|
||||
* <p/>
|
||||
* <!-- START SNIPPET: multipart-note -->
|
||||
* <p/>
|
||||
* You must set the encoding to <code>multipart/form-data</code> in the form where the user selects the file to upload.
|
||||
* <p/>
|
||||
* <!-- END SNIPPET: multipart-note -->
|
||||
* <p/>
|
||||
* <pre>
|
||||
* <!-- START SNIPPET: example-form -->
|
||||
* <s:form action="doUpload" method="post" enctype="multipart/form-data">
|
||||
* <s:file name="upload" label="File"/>
|
||||
* <s:submit/>
|
||||
* </s:form>
|
||||
* <!-- END SNIPPET: example-form -->
|
||||
* </pre>
|
||||
*
|
||||
* <p/>
|
||||
* And then in your action code you'll have access to the File object if you provide setters according to the
|
||||
* naming convention documented in the start.
|
||||
*
|
||||
* <p/>
|
||||
* <pre>
|
||||
* public com.examples.UploadAction implemements Action {
|
||||
* <!-- START SNIPPET: example-action -->
|
||||
* package com.example;
|
||||
* <p/>
|
||||
* import java.io.File;
|
||||
* import com.opensymphony.xwork2.ActionSupport;
|
||||
* <p/>
|
||||
* public UploadAction extends ActionSupport {
|
||||
* private File file;
|
||||
* private String contentType;
|
||||
* private String filename;
|
||||
*
|
||||
* <p/>
|
||||
* public void setUpload(File file) {
|
||||
* this.file = file;
|
||||
* }
|
||||
*
|
||||
* <p/>
|
||||
* public void setUploadContentType(String contentType) {
|
||||
* this.contentType = contentType;
|
||||
* }
|
||||
*
|
||||
* <p/>
|
||||
* public void setUploadFileName(String filename) {
|
||||
* this.filename = filename;
|
||||
* }
|
||||
*
|
||||
* ...
|
||||
* <p/>
|
||||
* public String execute() {
|
||||
* //...
|
||||
* return SUCCESS;
|
||||
* }
|
||||
* }
|
||||
* <!-- END SNIPPET: example-action -->
|
||||
* </pre>
|
||||
* <!-- END SNIPPET: example -->
|
||||
*
|
||||
*/
|
||||
public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
|
||||
private static final long serialVersionUID = -4764627478894962478L;
|
||||
|
||||
protected static final Logger LOG = LoggerFactory.getLogger(FileUploadInterceptor.class);
|
||||
private static final String DEFAULT_DELIMITER = ",";
|
||||
private static final String DEFAULT_MESSAGE = "no.message.found";
|
||||
|
||||
protected boolean useActionMessageBundle;
|
||||
|
||||
protected Long maximumSize;
|
||||
protected String allowedTypes;
|
||||
protected Set allowedTypesSet = Collections.EMPTY_SET;
|
||||
protected Set<String> allowedTypesSet = Collections.emptySet();
|
||||
protected Set<String> allowedExtensionsSet = Collections.emptySet();
|
||||
|
||||
public void setUseActionMessageBundle(String value) {
|
||||
this.useActionMessageBundle = Boolean.valueOf(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the allowed extensions
|
||||
*
|
||||
* @param allowedExtensions A comma-delimited list of extensions
|
||||
*/
|
||||
public void setAllowedExtensions(String allowedExtensions) {
|
||||
allowedExtensionsSet = TextParseUtil.commaDelimitedStringToSet(allowedExtensions);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the allowed mimetypes
|
||||
@@ -177,10 +206,7 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
* @param allowedTypes A comma-delimited list of types
|
||||
*/
|
||||
public void setAllowedTypes(String allowedTypes) {
|
||||
this.allowedTypes = allowedTypes;
|
||||
|
||||
// set the allowedTypes as a collection for easier access later
|
||||
allowedTypesSet = getDelimitedValues(allowedTypes);
|
||||
allowedTypesSet = TextParseUtil.commaDelimitedStringToSet(allowedTypes);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -197,20 +223,22 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
*/
|
||||
public String intercept(ActionInvocation invocation) throws Exception {
|
||||
ActionContext ac = invocation.getInvocationContext();
|
||||
|
||||
HttpServletRequest request = (HttpServletRequest) ac.get(ServletActionContext.HTTP_REQUEST);
|
||||
|
||||
if (!(request instanceof MultiPartRequestWrapper)) {
|
||||
if (LOG.isDebugEnabled()) {
|
||||
ActionProxy proxy = invocation.getProxy();
|
||||
LOG.debug(getTextMessage("struts.messages.bypass.request", new Object[]{proxy.getNamespace(), proxy.getActionName()}, ActionContext.getContext().getLocale()));
|
||||
LOG.debug(getTextMessage("struts.messages.bypass.request", new Object[]{proxy.getNamespace(), proxy.getActionName()}, ac.getLocale()));
|
||||
}
|
||||
|
||||
return invocation.invoke();
|
||||
}
|
||||
|
||||
final Object action = invocation.getAction();
|
||||
ValidationAware validation = null;
|
||||
|
||||
Object action = invocation.getAction();
|
||||
|
||||
if (action instanceof ValidationAware) {
|
||||
validation = (ValidationAware) action;
|
||||
}
|
||||
@@ -218,9 +246,7 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
MultiPartRequestWrapper multiWrapper = (MultiPartRequestWrapper) request;
|
||||
|
||||
if (multiWrapper.hasErrors()) {
|
||||
for (Iterator errorIter = multiWrapper.getErrors().iterator(); errorIter.hasNext();) {
|
||||
String error = (String) errorIter.next();
|
||||
|
||||
for (String error : multiWrapper.getErrors()) {
|
||||
if (validation != null) {
|
||||
validation.addActionError(error);
|
||||
}
|
||||
@@ -229,9 +255,7 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
}
|
||||
}
|
||||
|
||||
Map parameters = ac.getParameters();
|
||||
|
||||
// Bind allowed Files
|
||||
// bind allowed Files
|
||||
Enumeration fileParameterNames = multiWrapper.getFileParameterNames();
|
||||
while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
|
||||
// get the value of this input tag
|
||||
@@ -245,23 +269,36 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
String[] fileName = multiWrapper.getFileNames(inputName);
|
||||
|
||||
if (isNonEmpty(fileName)) {
|
||||
// Get a File object for the uploaded File
|
||||
// get a File object for the uploaded File
|
||||
File[] files = multiWrapper.getFiles(inputName);
|
||||
if (files != null) {
|
||||
for (int index = 0; index < files.length; index++) {
|
||||
if (files != null && files.length > 0) {
|
||||
List<File> acceptedFiles = new ArrayList<File>(files.length);
|
||||
List<String> acceptedContentTypes = new ArrayList<String>(files.length);
|
||||
List<String> acceptedFileNames = new ArrayList<String>(files.length);
|
||||
String contentTypeName = inputName + "ContentType";
|
||||
String fileNameName = inputName + "FileName";
|
||||
|
||||
if (acceptFile(files[index], contentType[index], inputName, validation, ac.getLocale())) {
|
||||
parameters.put(inputName, files);
|
||||
parameters.put(inputName + "ContentType", contentType);
|
||||
parameters.put(inputName + "FileName", fileName);
|
||||
for (int index = 0; index < files.length; index++) {
|
||||
if (acceptFile(action, files[index], fileName[index], contentType[index], inputName, validation, ac.getLocale())) {
|
||||
acceptedFiles.add(files[index]);
|
||||
acceptedContentTypes.add(contentType[index]);
|
||||
acceptedFileNames.add(fileName[index]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!acceptedFiles.isEmpty()) {
|
||||
Map<String, Object> params = ac.getParameters();
|
||||
|
||||
params.put(inputName, acceptedFiles.toArray(new File[acceptedFiles.size()]));
|
||||
params.put(contentTypeName, acceptedContentTypes.toArray(new String[acceptedContentTypes.size()]));
|
||||
params.put(fileNameName, acceptedFileNames.toArray(new String[acceptedFileNames.size()]));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
LOG.error(getTextMessage("struts.messages.invalid.file", new Object[]{inputName}, ActionContext.getContext().getLocale()));
|
||||
LOG.error(getTextMessage(action, "struts.messages.invalid.file", new Object[]{inputName}, ac.getLocale()));
|
||||
}
|
||||
} else {
|
||||
LOG.error(getTextMessage("struts.messages.invalid.content.type", new Object[]{inputName}, ActionContext.getContext().getLocale()));
|
||||
LOG.error(getTextMessage(action, "struts.messages.invalid.content.type", new Object[]{inputName}, ac.getLocale()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,12 +309,13 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
fileParameterNames = multiWrapper.getFileParameterNames();
|
||||
while (fileParameterNames != null && fileParameterNames.hasMoreElements()) {
|
||||
String inputValue = (String) fileParameterNames.nextElement();
|
||||
File[] file = multiWrapper.getFiles(inputValue);
|
||||
for (int index = 0; index < file.length; index++) {
|
||||
File currentFile = file[index];
|
||||
if(LOG.isInfoEnabled()) {
|
||||
LOG.info(getTextMessage("struts.messages.removing.file", new Object[]{inputValue, currentFile}, ActionContext.getContext().getLocale()));
|
||||
File[] files = multiWrapper.getFiles(inputValue);
|
||||
|
||||
for (File currentFile : files) {
|
||||
if (LOG.isInfoEnabled()) {
|
||||
LOG.info(getTextMessage(action, "struts.messages.removing.file", new Object[]{inputValue, currentFile}, ac.getLocale()));
|
||||
}
|
||||
|
||||
if ((currentFile != null) && currentFile.isFile()) {
|
||||
currentFile.delete();
|
||||
}
|
||||
@@ -290,6 +328,7 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
/**
|
||||
* Override for added functionality. Checks if the proposed file is acceptable based on contentType and size.
|
||||
*
|
||||
* @param action - uploading action for message retrieval.
|
||||
* @param file - proposed upload file.
|
||||
* @param contentType - contentType of the file.
|
||||
* @param inputName - inputName of the file.
|
||||
@@ -298,26 +337,33 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
* @param locale
|
||||
* @return true if the proposed file is acceptable by contentType and size.
|
||||
*/
|
||||
protected boolean acceptFile(File file, String contentType, String inputName, ValidationAware validation, Locale locale) {
|
||||
protected boolean acceptFile(Object action, File file, String filename, String contentType, String inputName, ValidationAware validation, Locale locale) {
|
||||
boolean fileIsAcceptable = false;
|
||||
|
||||
// If it's null the upload failed
|
||||
if (file == null) {
|
||||
String errMsg = getTextMessage("struts.messages.error.uploading", new Object[]{inputName}, locale);
|
||||
String errMsg = getTextMessage(action, "struts.messages.error.uploading", new Object[]{inputName}, locale);
|
||||
if (validation != null) {
|
||||
validation.addFieldError(inputName, errMsg);
|
||||
}
|
||||
|
||||
LOG.error(errMsg);
|
||||
} else if (maximumSize != null && maximumSize.longValue() < file.length()) {
|
||||
String errMsg = getTextMessage("struts.messages.error.file.too.large", new Object[]{inputName, file.getName(), "" + file.length()}, locale);
|
||||
} else if (maximumSize != null && maximumSize < file.length()) {
|
||||
String errMsg = getTextMessage(action, "struts.messages.error.file.too.large", new Object[]{inputName, filename, file.getName(), "" + file.length()}, locale);
|
||||
if (validation != null) {
|
||||
validation.addFieldError(inputName, errMsg);
|
||||
}
|
||||
|
||||
LOG.error(errMsg);
|
||||
} else if ((! allowedTypesSet.isEmpty()) && (!containsItem(allowedTypesSet, contentType))) {
|
||||
String errMsg = getTextMessage("struts.messages.error.content.type.not.allowed", new Object[]{inputName, file.getName(), contentType}, locale);
|
||||
} else if ((!allowedTypesSet.isEmpty()) && (!containsItem(allowedTypesSet, contentType))) {
|
||||
String errMsg = getTextMessage(action, "struts.messages.error.content.type.not.allowed", new Object[]{inputName, filename, file.getName(), contentType}, locale);
|
||||
if (validation != null) {
|
||||
validation.addFieldError(inputName, errMsg);
|
||||
}
|
||||
|
||||
LOG.error(errMsg);
|
||||
} else if ((! allowedExtensionsSet.isEmpty()) && (!hasAllowedExtension(allowedExtensionsSet, filename))) {
|
||||
String errMsg = getTextMessage(action, "struts.messages.error.file.extension.not.allowed", new Object[]{inputName, filename, file.getName(), contentType}, locale);
|
||||
if (validation != null) {
|
||||
validation.addFieldError(inputName, errMsg);
|
||||
}
|
||||
@@ -331,26 +377,32 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemCollection - Collection of string items (all lowercase).
|
||||
* @param key - Key to search for.
|
||||
* @return true if itemCollection contains the key, false otherwise.
|
||||
* @param extensionCollection - Collection of extensions (all lowercase).
|
||||
* @param filename - filename to check.
|
||||
* @return true if the filename has an allowed extension, false otherwise.
|
||||
*/
|
||||
private static boolean containsItem(Collection itemCollection, String key) {
|
||||
return itemCollection.contains(key.toLowerCase());
|
||||
}
|
||||
private static boolean hasAllowedExtension(Collection<String> extensionCollection, String filename) {
|
||||
if (filename == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
private static Set getDelimitedValues(String delimitedString) {
|
||||
Set<String> delimitedValues = new HashSet<String>();
|
||||
if (delimitedString != null) {
|
||||
StringTokenizer stringTokenizer = new StringTokenizer(delimitedString, DEFAULT_DELIMITER);
|
||||
while (stringTokenizer.hasMoreTokens()) {
|
||||
String nextToken = stringTokenizer.nextToken().toLowerCase().trim();
|
||||
if (nextToken.length() > 0) {
|
||||
delimitedValues.add(nextToken);
|
||||
}
|
||||
String lowercaseFilename = filename.toLowerCase();
|
||||
for (String extension : extensionCollection) {
|
||||
if (lowercaseFilename.endsWith(extension)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return delimitedValues;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param itemCollection - Collection of string items (all lowercase).
|
||||
* @param item - Item to search for.
|
||||
* @return true if itemCollection contains the item, false otherwise.
|
||||
*/
|
||||
private static boolean containsItem(Collection<String> itemCollection, String item) {
|
||||
return itemCollection.contains(item.toLowerCase());
|
||||
}
|
||||
|
||||
private static boolean isNonEmpty(Object[] objArray) {
|
||||
@@ -364,9 +416,19 @@ public class FileUploadInterceptor extends AbstractInterceptor {
|
||||
}
|
||||
|
||||
private String getTextMessage(String messageKey, Object[] args, Locale locale) {
|
||||
return getTextMessage(null, messageKey, args, locale);
|
||||
}
|
||||
|
||||
private String getTextMessage(Object action, String messageKey, Object[] args, Locale locale) {
|
||||
if (args == null || args.length == 0) {
|
||||
return LocalizedTextUtil.findText(this.getClass(), messageKey, locale);
|
||||
if ( action != null && useActionMessageBundle) {
|
||||
return LocalizedTextUtil.findText(action.getClass(), messageKey, locale);
|
||||
}
|
||||
return LocalizedTextUtil.findText(this.getClass(), messageKey, locale);
|
||||
} else {
|
||||
if ( action != null && useActionMessageBundle) {
|
||||
return LocalizedTextUtil.findText(action.getClass(), messageKey, locale, DEFAULT_MESSAGE, args);
|
||||
}
|
||||
return LocalizedTextUtil.findText(this.getClass(), messageKey, locale, DEFAULT_MESSAGE, args);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,5 +42,5 @@ public interface ParameterAware {
|
||||
*
|
||||
* @param parameters a Map of parameters (name/value Strings).
|
||||
*/
|
||||
public void setParameters(Map<String,String[]> parameters);
|
||||
public void setParameters(Map<String, String[]> parameters);
|
||||
}
|
||||
|
||||
@@ -98,11 +98,14 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
*
|
||||
* </ul>
|
||||
*
|
||||
* <li>sessionReset - boolean value causing all session values to be reset to action's default values or application
|
||||
* scope values, note that it is similliar to type="start" and in fact it does the same, but in our team it is sometimes
|
||||
* semantically preferred. We use session scope in two patterns - sometimes there are wizzard-like action sequences that
|
||||
* <li>sessionReset - name of a parameter (defaults to 'session.reset') which if set, causes all session values to be reset to action's default values or application
|
||||
* scope values, note that it is similar to type="start" and in fact it does the same, but in our team it is sometimes
|
||||
* semantically preferred. We use session scope in two patterns - sometimes there are wizard-like action sequences that
|
||||
* have start and end, and sometimes we just want simply reset current session values.</li>
|
||||
*
|
||||
* <li>reset - boolean, defaults to false, if set, it has the same effect as setting all session values to be reset to action's default values or application.</li>
|
||||
*
|
||||
* <li>autoCreateSession - boolean value, sets if the session should be automatically created.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <!-- END SNIPPET: parameters -->
|
||||
|
||||
@@ -135,7 +135,7 @@ public class ServletConfigInterceptor extends AbstractInterceptor implements Str
|
||||
}
|
||||
|
||||
if (action instanceof ParameterAware) {
|
||||
((ParameterAware) action).setParameters(context.getParameters());
|
||||
((ParameterAware) action).setParameters((Map)context.getParameters());
|
||||
}
|
||||
|
||||
if (action instanceof ApplicationAware) {
|
||||
|
||||
@@ -24,6 +24,7 @@ package org.apache.struts2.interceptor;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.struts2.util.TokenHelper;
|
||||
import org.apache.struts2.ServletActionContext;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
@@ -31,6 +32,8 @@ import com.opensymphony.xwork2.ValidationAware;
|
||||
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
|
||||
import com.opensymphony.xwork2.util.LocalizedTextUtil;
|
||||
|
||||
import javax.servlet.http.HttpSession;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: description -->
|
||||
*
|
||||
@@ -129,7 +132,9 @@ public class TokenInterceptor extends MethodFilterInterceptor {
|
||||
log.debug("Intercepting invocation to check for valid transaction token.");
|
||||
}
|
||||
|
||||
Map session = ActionContext.getContext().getSession();
|
||||
//see WW-2902: we need to use the real HttpSession here, as opposed to the map
|
||||
//that wraps the session, because a new wrap is created on every request
|
||||
HttpSession session = ServletActionContext.getRequest().getSession(true);
|
||||
|
||||
synchronized (session) {
|
||||
if (!TokenHelper.validToken()) {
|
||||
|
||||
+25
-6
@@ -22,8 +22,13 @@
|
||||
package org.apache.struts2.interceptor.validation;
|
||||
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.apache.commons.lang.ArrayUtils;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.util.AnnotationUtils;
|
||||
import com.opensymphony.xwork2.validator.ValidationInterceptor;
|
||||
|
||||
/**
|
||||
@@ -31,24 +36,38 @@ import com.opensymphony.xwork2.validator.ValidationInterceptor;
|
||||
* annotation, and if found, don't validate this action method
|
||||
*/
|
||||
public class AnnotationValidationInterceptor extends ValidationInterceptor {
|
||||
|
||||
|
||||
/** Auto-generated serialization id */
|
||||
private static final long serialVersionUID = 1813272797367431184L;
|
||||
|
||||
protected String doIntercept(ActionInvocation invocation) throws Exception {
|
||||
|
||||
|
||||
Object action = invocation.getAction();
|
||||
if (action != null) {
|
||||
Method method = getActionMethod(action.getClass(), invocation.getProxy().getMethod());
|
||||
SkipValidation skip = (SkipValidation) method.getAnnotation(SkipValidation.class);
|
||||
if (skip != null) {
|
||||
Collection<Method> annotatedMethods = AnnotationUtils.getAnnotatedMethods(action.getClass(), SkipValidation.class);
|
||||
if (annotatedMethods.contains(method))
|
||||
return invocation.invoke();
|
||||
|
||||
//check if method overwites an annotated method
|
||||
Class clazz = action.getClass().getSuperclass();
|
||||
while (clazz != null) {
|
||||
annotatedMethods = AnnotationUtils.getAnnotatedMethods(clazz, SkipValidation.class);
|
||||
if (annotatedMethods != null) {
|
||||
for (Method annotatedMethod : annotatedMethods) {
|
||||
if (annotatedMethod.getName().equals(method.getName())
|
||||
&& Arrays.equals(annotatedMethod.getParameterTypes(), method.getParameterTypes())
|
||||
&& Arrays.equals(annotatedMethod.getExceptionTypes(), method.getExceptionTypes()))
|
||||
return invocation.invoke();
|
||||
}
|
||||
}
|
||||
clazz = clazz.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return super.doIntercept(invocation);
|
||||
}
|
||||
|
||||
|
||||
// FIXME: This is copied from DefaultActionInvocation but should be exposed through the interface
|
||||
protected Method getActionMethod(Class actionClass, String methodName) throws NoSuchMethodException {
|
||||
Method method;
|
||||
|
||||
+12
-9
@@ -34,6 +34,7 @@ import org.apache.struts2.ServletActionContext;
|
||||
|
||||
import com.opensymphony.xwork2.Action;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.ModelDriven;
|
||||
import com.opensymphony.xwork2.ValidationAware;
|
||||
import com.opensymphony.xwork2.interceptor.MethodFilterInterceptor;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
@@ -43,7 +44,7 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
* <p>Serializes validation and action errors into JSON. This interceptor does not
|
||||
* perform any validation, so it must follow the 'validation' interceptor on the stack.
|
||||
* </p>
|
||||
*
|
||||
*
|
||||
* <p>This stack (defined in struts-default.xml) shows how to use this interceptor with the
|
||||
* 'validation' interceptor</p>
|
||||
* <pre>
|
||||
@@ -58,19 +59,19 @@ import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
* </pre>
|
||||
* <p>If 'validationFailedStatus' is set it will be used as the Response status
|
||||
* when validation fails.</p>
|
||||
*
|
||||
* <p>If the request has a parameter 'struts.validateOnly' execution will return after
|
||||
*
|
||||
* <p>If the request has a parameter 'struts.validateOnly' execution will return after
|
||||
* validation (action won't be executed).</p>
|
||||
*
|
||||
*
|
||||
* <p>A request parameter named 'enableJSONValidation' must be set to 'true' to
|
||||
* use this interceptor</p>
|
||||
*/
|
||||
public class JSONValidationInterceptor extends MethodFilterInterceptor {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(JSONValidationInterceptor.class);
|
||||
|
||||
|
||||
private static final String VALIDATE_ONLY_PARAM = "struts.validateOnly";
|
||||
private static final String VALIDATE_JSON_PARAM = "struts.enableJSONValidation";
|
||||
|
||||
|
||||
static char[] hex = "0123456789ABCDEF".toCharArray();
|
||||
|
||||
private int validationFailedStatus = -1;
|
||||
@@ -90,7 +91,7 @@ public class JSONValidationInterceptor extends MethodFilterInterceptor {
|
||||
|
||||
Object action = invocation.getAction();
|
||||
String jsonEnabled = request.getParameter(VALIDATE_JSON_PARAM);
|
||||
|
||||
|
||||
if (jsonEnabled != null && "true".equals(jsonEnabled)) {
|
||||
if (action instanceof ValidationAware) {
|
||||
// generate json
|
||||
@@ -130,7 +131,7 @@ public class JSONValidationInterceptor extends MethodFilterInterceptor {
|
||||
//action errors
|
||||
if (validationAware.hasActionErrors()) {
|
||||
sb.append("\"errors\":");
|
||||
sb.append(buildArray(validationAware.getActionErrors()));
|
||||
sb.append(buildArray(validationAware.getActionErrors()));
|
||||
}
|
||||
|
||||
//field errors
|
||||
@@ -143,7 +144,9 @@ public class JSONValidationInterceptor extends MethodFilterInterceptor {
|
||||
for (Map.Entry<String, List<String>> fieldError : fieldErrors
|
||||
.entrySet()) {
|
||||
sb.append("\"");
|
||||
sb.append(fieldError.getKey());
|
||||
//if it is model driven, remove "model." see WW-2721
|
||||
sb.append(validationAware instanceof ModelDriven ? fieldError.getKey().substring(6)
|
||||
: fieldError.getKey());
|
||||
sb.append("\":");
|
||||
sb.append(buildArray(fieldError.getValue()));
|
||||
sb.append(",");
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user