mirror of
https://github.com/apache/struts.git
synced 2026-08-10 17:16:58 +00:00
Compare commits
139 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 2c0facc3aa | |||
| 6ae63d7669 | |||
| eed364fe28 | |||
| 56c6456c61 | |||
| 20a7b6503f | |||
| 2eb809144a | |||
| 8ef8581d0c | |||
| caeea2145f | |||
| b5cfccace3 | |||
| 95a24c87a4 | |||
| 92e931d169 | |||
| e9a4bcd776 | |||
| 9b892cc7fd | |||
| 74460831dc | |||
| 8d4194bbf7 | |||
| cf71e0f34f | |||
| 97012c78a9 | |||
| f34cf78ae3 | |||
| 72058bf4c6 | |||
| 46462b3d00 | |||
| a9899b6622 | |||
| a3180e3069 | |||
| d5926b7a21 | |||
| 9beb940136 | |||
| 17b598433d | |||
| 86baf21098 | |||
| bba17b6496 | |||
| c3b85aef7c | |||
| 355e4b517f | |||
| 1ec1e71d41 | |||
| e23197ab1b | |||
| c21fb94921 | |||
| 9bf89f82dc | |||
| 29e1847f64 | |||
| 02b61b2c05 | |||
| d1df216b32 | |||
| 7518e809dd | |||
| 2b2de35519 | |||
| 87b2bd8138 | |||
| 215eb627d4 | |||
| 29b29a9c64 | |||
| 5e237e0fd3 | |||
| 23077d3ee9 | |||
| 4fbded7147 | |||
| f9f0f36d29 | |||
| f60095bae9 | |||
| e4a3669061 | |||
| 5e4b385984 | |||
| 38450c9a70 | |||
| df4a18107f | |||
| 9739291d79 | |||
| 4394238b7e | |||
| ff903e7754 | |||
| 77cbafb74d | |||
| faf50183e0 | |||
| 67bdf68419 | |||
| cf19d5130c | |||
| a66f92c66d | |||
| 08c058ea65 | |||
| cd0773fb1b | |||
| f803ddb16e | |||
| 0deea3f9e4 | |||
| 2fd2cb5f97 | |||
| 7df1e67bac | |||
| dd76d39224 | |||
| 476697f99a | |||
| 0bfdc5e643 | |||
| a29051c835 | |||
| 7a251ddca9 | |||
| 38e3734930 | |||
| fe65910e0e | |||
| 1d0b375afd | |||
| 0713da431c | |||
| 79951db2aa | |||
| d64365770d | |||
| b04683181c | |||
| fad603c49b | |||
| 87c2746fc7 | |||
| 49ef41c218 | |||
| e1767d9525 | |||
| 67b7fc3f3e | |||
| a4183b63f8 | |||
| 74dd8d6990 | |||
| 4152cbc71c | |||
| dd8ba56425 | |||
| 8eb282f76b | |||
| eabf4eda21 | |||
| 809d8968ca | |||
| 033573e8fb | |||
| 7cdc319b41 | |||
| 7116ac8801 | |||
| a2710a6f04 | |||
| 457f7c2f57 | |||
| 6fc695970f | |||
| 15e6be1d66 | |||
| eddab32e75 | |||
| fb23b719f2 | |||
| c4bd87e510 | |||
| 004b4981a1 | |||
| 8b608e334a | |||
| 031bd1aceb | |||
| 9078422496 | |||
| 278a2112b9 | |||
| 2941416a18 | |||
| 4738d1d802 | |||
| d4b620d06d | |||
| cf8ba17454 | |||
| a8ecd9bd29 | |||
| 6b131550a6 | |||
| dda3facc26 | |||
| d082aaca2a | |||
| 94758b699c | |||
| bfa119c7db | |||
| 7058872723 | |||
| 6c3316a14a | |||
| e717e469a4 | |||
| 80698ed516 | |||
| 9b9bd212ed | |||
| 0856157e27 | |||
| bea5537e9e | |||
| 7c7d5be441 | |||
| a728c74f21 | |||
| 76d0bc5ff4 | |||
| ad98881dd5 | |||
| 0207c09b11 | |||
| 5ef7687259 | |||
| 794cd5e141 | |||
| a2824b7c87 | |||
| 941374ecdb | |||
| 0d42ff50ac | |||
| 00b5f43c8a | |||
| 87967b9f84 | |||
| d36ec579fc | |||
| 0bde78cc36 | |||
| c14dca5be3 | |||
| 7c4f30f619 | |||
| c956d1a40d | |||
| a92eb529a9 | |||
| 882a6e803e |
+13
-1
@@ -6,4 +6,16 @@ jdk:
|
||||
- oraclejdk8
|
||||
|
||||
install: true
|
||||
script: mvn test -DskipAssembly
|
||||
script: mvn test -DskipAssembly
|
||||
|
||||
after_success:
|
||||
- mvn clean cobertura:cobertura org.eluder.coveralls:coveralls-maven-plugin:report com.updateimpact:updateimpact-maven-plugin:submit -Ptravis-coveralls,update-impact -DskipAssembly
|
||||
|
||||
env:
|
||||
global:
|
||||
secure: DusDFL9cuX+mj64tXQfrYVbUVYnxlXmad4nuIMj0/lgDbwJ6kxYasJmR99bdvwu08gS9D5b7a+m7WJTN0FNATzEiiGDXcM+TiDPlYDh7dcalU4QGiLmMuCCEw1r7hp2XE4BWVgDfFhCsHhStgjE4RXzHIyPowoPXr4ugPf8at6w=
|
||||
|
||||
cache:
|
||||
directories:
|
||||
- $HOME/.m2
|
||||
|
||||
@@ -1,41 +1,98 @@
|
||||
<!---
|
||||
Licensed to the Apache Software Foundation (ASF) under one or more
|
||||
contributor license agreements. See the NOTICE file distributed with
|
||||
this work for additional information regarding copyright ownership.
|
||||
The ASF licenses this file to You under the Apache License, Version 2.0
|
||||
(the "License"); you may not use this file except in compliance with
|
||||
the License. You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
-->
|
||||
The Apache Struts web framework
|
||||
-------------------------------
|
||||
|
||||
[](https://builds.apache.org/view/S-Z/view/Struts/job/Struts-master-JDK7/)
|
||||
[](https://travis-ci.org/apache/struts)
|
||||
[](https://maven-badges.herokuapp.com/maven-central/org.apache.struts/struts2-core/)
|
||||
[](https://coveralls.io/github/apache/struts)
|
||||
[](https://app.updateimpact.com/latest/713283867011846144/Struts%202)
|
||||
[](http://www.apache.org/licenses/LICENSE-2.0.html)
|
||||
|
||||
The Apache Struts web framework is a free open-source solution for creating Java web applications.
|
||||
|
||||
Web applications differ from conventional websites in that web applications can create a dynamic response. Many websites deliver only static pages. A web application can interact with databases and business logic engines to customize a response.
|
||||
## Documentation
|
||||
|
||||
Web applications based on JavaServer Pages sometimes commingle database code, page design code, and control flow code. In practice, we find that unless these concerns are separated, larger applications become difficult to maintain.
|
||||
More information can be found on the [homepage](https://struts.apache.org/). Please read the [Security Guide](https://struts.apache.org/security/)
|
||||
and the [JavaDocs](https://struts.apache.org/maven/struts2-core/apidocs/index.html) can be browsed.
|
||||
Questions related to the usage of the Apache Struts should be posted to the [user mailing list](https://struts.apache.org/mail.html).
|
||||
|
||||
One way to separate concerns in a software application is to use a Model-View-Controller (MVC) architecture. The Model represents the business or database code, the View represents the page design code, and the Controller represents the navigational code. The Struts framework is designed to help developers create web applications that utilize a MVC architecture.
|
||||
## Description
|
||||
|
||||
Web applications differ from conventional websites in that web applications can create a dynamic response. Many websites
|
||||
deliver only static pages. A web application can interact with databases and business logic engines to customize a response.
|
||||
|
||||
Web applications based on JavaServer Pages sometimes commingle database code, page design code, and control flow code.
|
||||
In practice, we find that unless these concerns are separated, larger applications become difficult to maintain.
|
||||
|
||||
One way to separate concerns in a software application is to use a Model-View-Controller (MVC) architecture. The Model
|
||||
represents the business or database code, the View represents the page design code, and the Controller represents
|
||||
the navigational code. The Struts framework is designed to help developers create web applications that utilize
|
||||
a MVC architecture.
|
||||
|
||||
The framework provides three key components:
|
||||
|
||||
A “request” handler provided by the application developer that is mapped to a standard URI. A “response” handler that transfers control to another resource which completes the response. A tag library that helps developers create interactive form-based applications with server pages. The framework’s architecture and tags are buzzword compliant. Struts works well with conventional REST applications and with technologies like SOAP and AJAX.
|
||||
A “request” handler provided by the application developer that is mapped to a standard URI. A “response” handler that
|
||||
transfers control to another resource which completes the response. A tag library that helps developers create interactive
|
||||
form-based applications with server pages. The framework’s architecture and tags are buzzword compliant. Struts works well
|
||||
with conventional REST applications and with technologies like SOAP and AJAX.
|
||||
|
||||
The Apache Struts Project
|
||||
-------------------------
|
||||
## The Apache Struts Project
|
||||
|
||||
The Apache Struts Project is the open source community that creates and maintains the Apache Struts framework. The project consists of a diverse group of volunteers who share common values regarding collaborative, community-based open source development. The Apache Struts Project is proud to share these values with our parent organization: The Apache Software Foundation.
|
||||
The Apache Struts Project is the open source community that creates and maintains the Apache Struts framework.
|
||||
The project consists of a diverse group of volunteers who share common values regarding collaborative, community-based
|
||||
open source development. The Apache Struts Project is proud to share these values with our parent organization:
|
||||
The Apache Software Foundation.
|
||||
|
||||
The project is called “Struts” because the framework is meant to furnish the “invisible underpinnings” that support professional application development. Struts provides the glue that joins the various elements of the standard Java platform into a coherent whole. Our goal is to leverage existing standards by producing the missing pieces we need to create enterprise-grade applications that are easy to maintain over time.
|
||||
The project is called “Struts” because the framework is meant to furnish the “invisible underpinnings” that support
|
||||
professional application development. Struts provides the glue that joins the various elements of the standard Java
|
||||
platform into a coherent whole. Our goal is to leverage existing standards by producing the missing pieces we need to create
|
||||
enterprise-grade applications that are easy to maintain over time.
|
||||
|
||||
The Apache Struts Project offered two major versions of the Struts framework. Currently we are only maintaining the Struts 2 version. It is recommended to upgrade all Struts 1.x application to Struts 2. Please do not start new application development using Struts 1.x, as we are no longer issuing security patches.
|
||||
The Apache Struts Project offered two major versions of the Struts framework. Currently we are only maintaining the Struts 2
|
||||
version. It is recommended to upgrade all Struts 1.x application to Struts 2. Please do not start new application development
|
||||
using Struts 1.x, as we are no longer issuing security patches.
|
||||
|
||||
Struts 2 was originally known as WebWork 2. After working independently for several years, the WebWork and Struts communities joined forces to create Struts 2. The 2.x framework is the best choice for teams who value elegant solutions to difficult problems.
|
||||
Struts 2 was originally known as WebWork 2. After working independently for several years, the WebWork and Struts
|
||||
communities joined forces to create Struts 2. The 2.x framework is the best choice for teams who value elegant solutions
|
||||
to difficult problems.
|
||||
|
||||
Why should you use Apache Struts?
|
||||
---------------------------------
|
||||
## Why should you use Apache Struts?
|
||||
|
||||
Apache Struts is a modern, maintained and full-featured web framework. It has been there for years and give the huge user base it is unlikely it will go away anytime soon in the future. Not only that we have dedicated users and developers on the project. Apache Struts is licensed to the Apache License 2.0 and this will not change. We maintain a clean IP and you are “safe” to use the project. Sometimes you are not “safe” to use a project when a company controls the SCM. Access to Source Code doesn’t mean it is free. With Apache Struts, you are not only free to “do what you want with it”, you can even contribute (which is not always the case). And best of it: you can become a part of the core team too.
|
||||
Apache Struts is a modern, maintained and full-featured web framework. It has been there for years and give the huge user
|
||||
base it is unlikely it will go away anytime soon in the future. Not only that we have dedicated users and developers
|
||||
on the project. Apache Struts is licensed to the Apache License 2.0 and this will not change. We maintain a clean IP
|
||||
and you are “safe” to use the project. Sometimes you are not “safe” to use a project when a company controls the SCM.
|
||||
Access to Source Code doesn’t mean it is free. With Apache Struts, you are not only free to “do what you want with it”,
|
||||
you can even contribute (which is not always the case). And best of it: you can become a part of the core team too.
|
||||
|
||||
It is usually very easy to integrate other technologies with Apache Struts. If you are using an ORM like Apache Cayenne, Hibernate or JDBC you will not have any restrictions. Apache Struts is not even tied too much to a frontend technology. In old days it was JSP, then came Velocity and Freemarker. Nowadays you might build your web application with just static HTML and AngularJS. Or you want to use Sitemesh or Tiles. This all is no problem due to Struts elegant and easy to use extension mechanisms.
|
||||
It is usually very easy to integrate other technologies with Apache Struts. If you are using an ORM like Apache Cayenne,
|
||||
Hibernate or JDBC you will not have any restrictions. Apache Struts is not even tied too much to a frontend technology.
|
||||
In old days it was JSP, then came Velocity and Freemarker. Nowadays you might build your web application with just static
|
||||
HTML and AngularJS. Or you want to use Sitemesh or Tiles. This all is no problem due to Struts elegant and easy to use
|
||||
extension mechanisms.
|
||||
|
||||
Unlike other, component oriented frameworks, we do not aim to hide the stateless nature of the web. We think it is perfectly acceptable to build upon a Request/Response cycle. We also think the MVC pattern is not so bad, just because it is old. In fact, we believe the Apache Struts architecture is clean and easy to understand.
|
||||
Unlike other, component oriented frameworks, we do not aim to hide the stateless nature of the web. We think it is
|
||||
perfectly acceptable to build upon a Request/Response cycle. We also think the MVC pattern is not so bad, just because
|
||||
it is old. In fact, we believe the Apache Struts architecture is clean and easy to understand.
|
||||
|
||||
Of course, if you wish to build components on the server side which render on the front end side, you are most likely wrong with Struts. This is a different approach which promises to reduce the amount of HTML/JavaScript knowledge needed and to create reusable components for the view layer. Projects like Wicket and Tapestry serve this purpose very well. As with every framework you need to decide if it makes sense for you to build components or if you are better with the Struts-approach.
|
||||
Of course, if you wish to build components on the server side which render on the front end side, you are most likely
|
||||
wrong with Struts. This is a different approach which promises to reduce the amount of HTML/JavaScript knowledge needed
|
||||
and to create reusable components for the view layer. Projects like Wicket and Tapestry serve this purpose very well.
|
||||
As with every framework you need to decide if it makes sense for you to build components or if you are better with
|
||||
the Struts-approach.
|
||||
|
||||
+2
-2
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
</parent>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<packaging>pom</packaging>
|
||||
@@ -99,7 +99,7 @@
|
||||
<dependency>
|
||||
<groupId>org.springframework</groupId>
|
||||
<artifactId>spring-test</artifactId>
|
||||
<version>${struts2.springPlatformVersion}</version>
|
||||
<version>${spring.platformVersion}</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
@@ -24,12 +24,12 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-rest-showcase</artifactId>
|
||||
<packaging>war</packaging>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
<name>Struts 2 Rest Showcase Webapp</name>
|
||||
<description>Struts 2 Rest Showcase Example</description>
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-apps</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-showcase</artifactId>
|
||||
|
||||
+30
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.showcase.tag.nonui.debugtag;
|
||||
|
||||
import com.opensymphony.xwork2.ActionSupport;
|
||||
import org.apache.struts2.dispatcher.PrepareOperations;
|
||||
|
||||
public class DebugTagAction extends ActionSupport {
|
||||
|
||||
public String execute() throws Exception {
|
||||
PrepareOperations.overrideDevMode(true); // Just for Showcase, explicitly switch on for this action only
|
||||
return SUCCESS;
|
||||
}
|
||||
}
|
||||
@@ -151,7 +151,7 @@
|
||||
<action name="date">
|
||||
<result>/WEB-INF/tags/non-ui/date.jsp</result>
|
||||
</action>
|
||||
<action name="debugTagDemo">
|
||||
<action name="debugTagDemo" class="org.apache.struts2.showcase.tag.nonui.debugtag.DebugTagAction">
|
||||
<result>/WEB-INF/tags/non-ui/debug.jsp</result>
|
||||
</action>
|
||||
</package>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-assembly</artifactId>
|
||||
|
||||
+3
-3
@@ -30,7 +30,7 @@
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-bom</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Struts 2 Bill of Materials</name>
|
||||
@@ -45,7 +45,7 @@
|
||||
</licenses>
|
||||
|
||||
<properties>
|
||||
<struts-version.version>2.5.14</struts-version.version>
|
||||
<struts-version.version>2.5.15</struts-version.version>
|
||||
<maven.site.skip>true</maven.site.skip>
|
||||
<maven.site.deploy.skip>true</maven.site.deploy.skip>
|
||||
</properties>
|
||||
@@ -181,6 +181,6 @@
|
||||
</dependencyManagement>
|
||||
|
||||
<scm>
|
||||
<tag>STRUTS_2_5_14</tag>
|
||||
<tag>STRUTS_2_5_15</tag>
|
||||
</scm>
|
||||
</project>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-admin-bundle</artifactId>
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-demo-bundle</artifactId>
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>struts2-osgi-bundles</artifactId>
|
||||
|
||||
+1
-3
@@ -24,7 +24,7 @@
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-parent</artifactId>
|
||||
<version>2.5.14</version>
|
||||
<version>2.5.15</version>
|
||||
</parent>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
@@ -40,7 +40,6 @@
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-surefire-plugin</artifactId>
|
||||
<version>2.6</version>
|
||||
<configuration>
|
||||
<argLine>-Duser.language=en -Duser.region=US</argLine>
|
||||
<properties>
|
||||
@@ -65,7 +64,6 @@
|
||||
<exclude>**/TestBean2.java</exclude>
|
||||
<exclude>**/TestInterceptor.java</exclude>
|
||||
<exclude>**/AnnotatedTestBean.java</exclude>
|
||||
<exclude>**/ContainerImplTest.java</exclude>
|
||||
<exclude>**/DefaultFileManagerTest.java</exclude>
|
||||
</excludes>
|
||||
</configuration>
|
||||
|
||||
@@ -21,8 +21,6 @@ package com.opensymphony.xwork2;
|
||||
import com.opensymphony.xwork2.interceptor.PreResultListener;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
/**
|
||||
* An {@link ActionInvocation} represents the execution state of an {@link Action}. It holds the Interceptors and the Action instance.
|
||||
* By repeated re-entrant execution of the <code>invoke()</code> method, initially by the {@link ActionProxy}, then by the Interceptors, the
|
||||
@@ -31,7 +29,7 @@ import java.io.Serializable;
|
||||
* @author Jason Carreira
|
||||
* @see com.opensymphony.xwork2.ActionProxy
|
||||
*/
|
||||
public interface ActionInvocation extends Serializable {
|
||||
public interface ActionInvocation {
|
||||
|
||||
/**
|
||||
* Get the Action associated with this ActionInvocation.
|
||||
@@ -178,20 +176,4 @@ public interface ActionInvocation extends Serializable {
|
||||
|
||||
void init(ActionProxy proxy) ;
|
||||
|
||||
/**
|
||||
* Prepares instance of ActionInvocation to be serializable,
|
||||
* which simple means removing all unserializable fields, eg. Container
|
||||
*
|
||||
* @return ActionInvocation which can be serialize (eg. into HttpSession)
|
||||
*/
|
||||
ActionInvocation serialize();
|
||||
|
||||
/**
|
||||
* Performs opposite process to restore back ActionInvocation after deserialisation
|
||||
*
|
||||
* @param actionContext current {@link ActionContext}
|
||||
* @return fully operational ActionInvocation
|
||||
*/
|
||||
ActionInvocation deserialize(ActionContext actionContext);
|
||||
|
||||
}
|
||||
|
||||
@@ -500,27 +500,4 @@ public class DefaultActionInvocation implements ActionInvocation {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Version ready to be serialize
|
||||
*
|
||||
* @return instance without reference to {@link Container}
|
||||
*/
|
||||
public ActionInvocation serialize() {
|
||||
DefaultActionInvocation that = this;
|
||||
that.container = null;
|
||||
return that;
|
||||
}
|
||||
|
||||
/**
|
||||
* Restoring Container
|
||||
*
|
||||
* @param actionContext current {@link ActionContext}
|
||||
* @return instance which can be used to invoke action
|
||||
*/
|
||||
public ActionInvocation deserialize(ActionContext actionContext) {
|
||||
DefaultActionInvocation that = this;
|
||||
that.container = actionContext.getContainer();
|
||||
return that;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -74,6 +74,10 @@ public abstract class XWorkJUnit4TestCase {
|
||||
return impl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return impl.getClass();
|
||||
}
|
||||
}, Scope.SINGLETON);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -82,7 +82,11 @@ public abstract class XWorkTestCase extends TestCase {
|
||||
public Object create(Context context) throws Exception {
|
||||
return impl;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return impl.getClass();
|
||||
}
|
||||
}, Scope.SINGLETON);
|
||||
}
|
||||
});
|
||||
|
||||
@@ -56,7 +56,7 @@ public class AllowedMethods {
|
||||
if (isPattern && !method.startsWith("regex:") && !strictMethodInvocation) {
|
||||
allowedMethods.add(new PatternAllowedMethod(methodPattern.toString(), method));
|
||||
} else if (method.startsWith("regex:")) {
|
||||
String pattern = method.substring(method.indexOf(":") + 1);
|
||||
String pattern = method.substring(method.indexOf(':') + 1);
|
||||
allowedMethods.add(new PatternAllowedMethod(pattern, method));
|
||||
} else if (method.contains("*") && !method.startsWith("regex:") && !strictMethodInvocation) {
|
||||
String pattern = method.replace("*", defaultRegex);
|
||||
|
||||
@@ -154,15 +154,15 @@ public abstract class AbstractMatcher<E> implements Serializable {
|
||||
Map<String, String> map = new LinkedHashMap<>();
|
||||
|
||||
//this will set the group index references, like {1}
|
||||
for (String key : orig.keySet()) {
|
||||
map.put(key, convertParam(orig.get(key), vars));
|
||||
for (Map.Entry<String,String> entry : orig.entrySet()) {
|
||||
map.put(entry.getKey(), convertParam(entry.getValue(), vars));
|
||||
}
|
||||
|
||||
//the values map will contain entries like name->"Lex Luthor" and 1->"Lex Luthor"
|
||||
//now add the non-numeric values
|
||||
for (String key: vars.keySet()) {
|
||||
if (!NumberUtils.isNumber(key)) {
|
||||
map.put(key, vars.get(key));
|
||||
for (Map.Entry<String,String> entry: vars.entrySet()) {
|
||||
if (!NumberUtils.isCreatable(entry.getKey())) {
|
||||
map.put(entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -59,8 +59,8 @@ public class ActionConfigMatcher extends AbstractMatcher<ActionConfig> implement
|
||||
Map<String, ActionConfig> configs,
|
||||
boolean looseMatch) {
|
||||
super(patternMatcher);
|
||||
for (String name : configs.keySet()) {
|
||||
addPattern(name, configs.get(name), looseMatch);
|
||||
for (Map.Entry<String, ActionConfig> entry : configs.entrySet()) {
|
||||
addPattern(entry.getKey(), entry.getValue(), looseMatch);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -172,6 +172,11 @@ public class DefaultConfiguration implements Configuration {
|
||||
public Configuration create(Context context) throws Exception {
|
||||
return DefaultConfiguration.this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Configuration> type() {
|
||||
return DefaultConfiguration.this.getClass();
|
||||
}
|
||||
});
|
||||
|
||||
ActionContext oldContext = ActionContext.getContext();
|
||||
@@ -419,8 +424,8 @@ public class DefaultConfiguration implements Configuration {
|
||||
this.namespaceActionConfigMatchers = new LinkedHashMap<>();
|
||||
this.namespaceMatcher = new NamespaceMatcher(matcher, namespaceActionConfigs.keySet());
|
||||
|
||||
for (String ns : namespaceActionConfigs.keySet()) {
|
||||
namespaceActionConfigMatchers.put(ns, new ActionConfigMatcher(matcher, namespaceActionConfigs.get(ns), true));
|
||||
for (Map.Entry<String, Map<String, ActionConfig>> entry : namespaceActionConfigs.entrySet()) {
|
||||
namespaceActionConfigMatchers.put(entry.getKey(), new ActionConfigMatcher(matcher, entry.getValue(), true));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -496,11 +501,11 @@ public class DefaultConfiguration implements Configuration {
|
||||
public String toString() {
|
||||
StringBuilder buff = new StringBuilder("RuntimeConfiguration - actions are\n");
|
||||
|
||||
for (String namespace : namespaceActionConfigs.keySet()) {
|
||||
Map<String, ActionConfig> actionConfigs = namespaceActionConfigs.get(namespace);
|
||||
for (Map.Entry<String, Map<String, ActionConfig>> entry : namespaceActionConfigs.entrySet()) {
|
||||
Map<String, ActionConfig> actionConfigs = entry.getValue();
|
||||
|
||||
for (String s : actionConfigs.keySet()) {
|
||||
buff.append(namespace).append("/").append(s).append("\n");
|
||||
buff.append(entry.getKey()).append("/").append(s).append("\n");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+6
-1
@@ -36,7 +36,12 @@ public class LocatableConstantFactory<T> extends Located implements Factory {
|
||||
public T create(Context ignored) {
|
||||
return constant;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return constant.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
@@ -51,6 +51,11 @@ public class LocatableFactory<T> extends Located implements Factory<T> {
|
||||
return (T) obj;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return implementation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
String fields = new LinkedHashMap<String, Object>() {
|
||||
|
||||
@@ -130,8 +130,8 @@ public class InterceptorBuilder {
|
||||
* interceptorStack1 -> [interceptor1.param1 -> someValue, interceptor1.param2 -> anotherValue]
|
||||
*
|
||||
*/
|
||||
for (String key : refParams.keySet()) {
|
||||
String value = refParams.get(key);
|
||||
for (Map.Entry<String, String> entry : refParams.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
|
||||
try {
|
||||
String name = key.substring(0, key.indexOf('.'));
|
||||
@@ -144,7 +144,7 @@ public class InterceptorBuilder {
|
||||
map = new LinkedHashMap<>();
|
||||
}
|
||||
|
||||
map.put(key, value);
|
||||
map.put(key, entry.getValue());
|
||||
params.put(name, map);
|
||||
|
||||
} catch (Exception e) {
|
||||
@@ -154,9 +154,9 @@ public class InterceptorBuilder {
|
||||
|
||||
result = new ArrayList<>(stackConfig.getInterceptors());
|
||||
|
||||
for (String key : params.keySet()) {
|
||||
|
||||
Map<String, String> map = params.get(key);
|
||||
for (Map.Entry<String, Map<String, String>> entry : params.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
Map<String, String> map = entry.getValue();
|
||||
|
||||
|
||||
Object interceptorCfgObj = interceptorLocator.getInterceptorConfig(key);
|
||||
|
||||
+1
@@ -113,6 +113,7 @@ import ognl.PropertyAccessor;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
import org.apache.struts2.dispatcher.Parameter;
|
||||
import org.apache.struts2.factory.PrefixBasedActionProxyFactory;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
|
||||
+1
-3
@@ -18,12 +18,10 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2.conversion;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Initializable;
|
||||
|
||||
/**
|
||||
* Used to read converters from Properties file
|
||||
*/
|
||||
public interface ConversionPropertiesProcessor extends Initializable {
|
||||
public interface ConversionPropertiesProcessor {
|
||||
|
||||
/**
|
||||
* Process given property to load converters as not required (Properties file doesn't have to exist)
|
||||
|
||||
+7
-8
@@ -82,15 +82,15 @@ import java.lang.annotation.Target;
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>converter</td>
|
||||
* <td>DEPRECATED: either this or value</td>
|
||||
* <td>either this or value</td>
|
||||
* <td> </td>
|
||||
* <td>The class name of the TypeConverter to be used as converter.</td>
|
||||
* <td>The class or bean name of the TypeConverter to be used as converter.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>converterClass</td>
|
||||
* <td>either this or value</td>
|
||||
* <td> </td>
|
||||
* <td>The class of the TypeConverter to be used as converter. XWorkBasicConverter by default.</td>
|
||||
* <td>XWorkBasicConverter</td>
|
||||
* <td>The class of the TypeConverter to be used as converter.</td>
|
||||
* </tr>
|
||||
* <tr>
|
||||
* <td>value</td>
|
||||
@@ -181,14 +181,13 @@ public @interface TypeConversion {
|
||||
ConversionRule rule() default ConversionRule.PROPERTY;
|
||||
|
||||
/**
|
||||
* The class of the TypeConverter to be used as converter.
|
||||
* The class or bean name of the TypeConverter to be used as converter.
|
||||
*
|
||||
* Note: This can not be used with ConversionRule.KEY_PROPERTY!
|
||||
*
|
||||
* @return class of the TypeConverter to be used as converter
|
||||
* @deprecated user {@link #converterClass()} instead
|
||||
* @return class or bean name of the TypeConverter to be used as converter
|
||||
* @see {@link #converterClass()}
|
||||
*/
|
||||
@Deprecated
|
||||
String converter() default "";
|
||||
|
||||
/**
|
||||
|
||||
+12
-7
@@ -26,6 +26,7 @@ import com.opensymphony.xwork2.conversion.annotations.ConversionRule;
|
||||
import com.opensymphony.xwork2.conversion.annotations.ConversionType;
|
||||
import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ClassLoaderUtil;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -69,7 +70,7 @@ public class DefaultConversionAnnotationProcessor implements ConversionAnnotatio
|
||||
mapping.put(key, tc.value());
|
||||
}
|
||||
//for properties of classes
|
||||
else if (tc.rule() != ConversionRule.ELEMENT || tc.rule() == ConversionRule.KEY || tc.rule() == ConversionRule.COLLECTION) {
|
||||
else if (tc.rule() != ConversionRule.ELEMENT && tc.rule() != ConversionRule.KEY && tc.rule() != ConversionRule.COLLECTION) {
|
||||
if (StringUtils.isNoneEmpty(tc.converter())) {
|
||||
mapping.put(key, converterCreator.createTypeConverter(tc.converter()));
|
||||
} else {
|
||||
@@ -80,18 +81,22 @@ public class DefaultConversionAnnotationProcessor implements ConversionAnnotatio
|
||||
else if (tc.rule() == ConversionRule.KEY) {
|
||||
Class<?> converterClass;
|
||||
if (StringUtils.isNoneEmpty(tc.converter())) {
|
||||
converterClass = Thread.currentThread().getContextClassLoader().loadClass(tc.converter());
|
||||
//check if the converter is a type converter if it is one
|
||||
//then just put it in the map as is. Otherwise
|
||||
//put a value in for the type converter of the class
|
||||
converterClass = ClassLoaderUtil.loadClass(tc.converter(), this.getClass());
|
||||
} else {
|
||||
converterClass = tc.converterClass();
|
||||
}
|
||||
|
||||
LOG.debug("Converter class: [{}]", converterClass);
|
||||
|
||||
//check if the converter is a type converter if it is one
|
||||
//then just put it in the map as is. Otherwise
|
||||
//put a value in for the type converter of the class
|
||||
if (converterClass.isAssignableFrom(TypeConverter.class)) {
|
||||
mapping.put(key, converterCreator.createTypeConverter(tc.converter()));
|
||||
if (StringUtils.isNoneEmpty(tc.converter())) {
|
||||
mapping.put(key, converterCreator.createTypeConverter(tc.converter()));
|
||||
} else {
|
||||
mapping.put(key, converterCreator.createTypeConverter(tc.converterClass()));
|
||||
}
|
||||
} else {
|
||||
mapping.put(key, converterClass);
|
||||
LOG.debug("Object placed in mapping for key [{}] is [{}]", key, mapping.get(key));
|
||||
@@ -100,7 +105,7 @@ public class DefaultConversionAnnotationProcessor implements ConversionAnnotatio
|
||||
//elements(values) of maps / lists
|
||||
else {
|
||||
if (StringUtils.isNoneEmpty(tc.converter())) {
|
||||
mapping.put(key, Thread.currentThread().getContextClassLoader().loadClass(tc.converter()));
|
||||
mapping.put(key, ClassLoaderUtil.loadClass(tc.converter(), this.getClass()));
|
||||
} else {
|
||||
mapping.put(key, tc.converterClass());
|
||||
}
|
||||
|
||||
+2
-2
@@ -86,7 +86,7 @@ public class DefaultConversionFileProcessor implements ConversionFileProcessor {
|
||||
//for keys of Maps
|
||||
else if (key.startsWith(DefaultObjectTypeDeterminer.KEY_PREFIX)) {
|
||||
|
||||
Class converterClass = Thread.currentThread().getContextClassLoader().loadClass((String) entry.getValue());
|
||||
Class converterClass = ClassLoaderUtil.loadClass((String) entry.getValue(), this.getClass());
|
||||
|
||||
//check if the converter is a type converter if it is one
|
||||
//then just put it in the map as is. Otherwise
|
||||
@@ -102,7 +102,7 @@ public class DefaultConversionFileProcessor implements ConversionFileProcessor {
|
||||
}
|
||||
//elements(values) of maps / lists
|
||||
else {
|
||||
Class _c = Thread.currentThread().getContextClassLoader().loadClass((String) entry.getValue());
|
||||
Class _c = ClassLoaderUtil.loadClass((String) entry.getValue(), this.getClass());
|
||||
LOG.debug("\t{}:{} [treated as Class {}]", key, entry.getValue(), _c);
|
||||
mapping.put(key, _c);
|
||||
}
|
||||
|
||||
+3
-1
@@ -23,6 +23,8 @@ import com.opensymphony.xwork2.conversion.ConversionPropertiesProcessor;
|
||||
import com.opensymphony.xwork2.conversion.TypeConverter;
|
||||
import com.opensymphony.xwork2.conversion.TypeConverterCreator;
|
||||
import com.opensymphony.xwork2.conversion.TypeConverterHolder;
|
||||
import com.opensymphony.xwork2.inject.EarlyInitializable;
|
||||
import com.opensymphony.xwork2.inject.Initializable;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ClassLoaderUtil;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
@@ -34,7 +36,7 @@ import java.util.Iterator;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
public class DefaultConversionPropertiesProcessor implements ConversionPropertiesProcessor {
|
||||
public class DefaultConversionPropertiesProcessor implements ConversionPropertiesProcessor, EarlyInitializable {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(DefaultConversionPropertiesProcessor.class);
|
||||
|
||||
|
||||
@@ -412,8 +412,8 @@ public class XWorkConverter extends DefaultTypeConverter {
|
||||
Object converter = mapping.get(property);
|
||||
if (converter == null && LOG.isDebugEnabled()) {
|
||||
LOG.debug("Converter is null for property [{}]. Mapping size [{}]:", property, mapping.size());
|
||||
for (String next : mapping.keySet()) {
|
||||
LOG.debug("{}:{}", next, mapping.get(next));
|
||||
for (Map.Entry<String, Object> entry : mapping.entrySet()) {
|
||||
LOG.debug("{}:{}", entry.getKey(), entry.getValue());
|
||||
}
|
||||
}
|
||||
return converter;
|
||||
@@ -500,15 +500,32 @@ public class XWorkConverter extends DefaultTypeConverter {
|
||||
for (Annotation annotation : annotations) {
|
||||
if (annotation instanceof TypeConversion) {
|
||||
TypeConversion tc = (TypeConversion) annotation;
|
||||
if (mapping.containsKey(tc.key())) {
|
||||
break;
|
||||
}
|
||||
String key = tc.key();
|
||||
// Default to the property name
|
||||
// Default to the property name with prefix
|
||||
if (StringUtils.isEmpty(key)) {
|
||||
key = AnnotationUtils.resolvePropertyName(method);
|
||||
switch (tc.rule()) {
|
||||
case COLLECTION:
|
||||
key = DefaultObjectTypeDeterminer.DEPRECATED_ELEMENT_PREFIX + key;
|
||||
break;
|
||||
case CREATE_IF_NULL:
|
||||
key = DefaultObjectTypeDeterminer.CREATE_IF_NULL_PREFIX + key;
|
||||
break;
|
||||
case ELEMENT:
|
||||
key = DefaultObjectTypeDeterminer.ELEMENT_PREFIX + key;
|
||||
break;
|
||||
case KEY:
|
||||
key = DefaultObjectTypeDeterminer.KEY_PREFIX + key;
|
||||
break;
|
||||
case KEY_PROPERTY:
|
||||
key = DefaultObjectTypeDeterminer.KEY_PROPERTY_PREFIX + key;
|
||||
break;
|
||||
}
|
||||
LOG.debug("Retrieved key [{}] from method name [{}]", key, method.getName());
|
||||
}
|
||||
if (mapping.containsKey(key)) {
|
||||
break;
|
||||
}
|
||||
annotationProcessor.process(mapping, tc, key);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public final class ContainerBuilder {
|
||||
|
||||
final Map<Key<?>, InternalFactory<?>> factories = new HashMap<>();
|
||||
final List<InternalFactory<?>> singletonFactories = new ArrayList<>();
|
||||
final List<InternalFactory<?>> initializableFactories = new ArrayList<>();
|
||||
final List<InternalFactory<?>> earlyInitializableFactories = new ArrayList<>();
|
||||
final List<Class<?>> staticInjections = new ArrayList<>();
|
||||
boolean created;
|
||||
boolean allowDuplicates = false;
|
||||
@@ -57,6 +57,11 @@ public final class ContainerBuilder {
|
||||
public Container create(InternalContext context) {
|
||||
return context.getContainer();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Container> type() {
|
||||
return Container.class;
|
||||
}
|
||||
};
|
||||
|
||||
private static final InternalFactory<Logger> LOGGER_FACTORY =
|
||||
@@ -66,6 +71,11 @@ public final class ContainerBuilder {
|
||||
return member == null ? Logger.getAnonymousLogger()
|
||||
: Logger.getLogger(member.getDeclaringClass().getName());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends Logger> type() {
|
||||
return Logger.class;
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -89,12 +99,14 @@ public final class ContainerBuilder {
|
||||
checkKey(key);
|
||||
final InternalFactory<? extends T> scopedFactory = scope.scopeFactory(key.getType(), key.getName(), factory);
|
||||
factories.put(key, scopedFactory);
|
||||
if (scope == Scope.SINGLETON) {
|
||||
singletonFactories.add(createCallableFactory(key, scopedFactory));
|
||||
}
|
||||
if (Initializable.class.isAssignableFrom(key.getType())) {
|
||||
initializableFactories.add(createCallableFactory(key, scopedFactory));
|
||||
|
||||
InternalFactory<T> callableFactory = createCallableFactory(key, scopedFactory);
|
||||
if (EarlyInitializable.class.isAssignableFrom(factory.type())) {
|
||||
earlyInitializableFactories.add(callableFactory);
|
||||
} else if (scope == Scope.SINGLETON) {
|
||||
singletonFactories.add(callableFactory);
|
||||
}
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
@@ -108,6 +120,11 @@ public final class ContainerBuilder {
|
||||
context.setExternalContext(null);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return scopedFactory.type();
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@@ -145,6 +162,11 @@ public final class ContainerBuilder {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return factory.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new LinkedHashMap<String, Object>() {{
|
||||
@@ -231,6 +253,11 @@ public final class ContainerBuilder {
|
||||
return (T) constructor.construct(context, type);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return implementation;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new LinkedHashMap<String, Object>() {{
|
||||
@@ -515,6 +542,11 @@ public final class ContainerBuilder {
|
||||
return value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return (Class<? extends T>) value.getClass();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return new LinkedHashMap<String, Object>() {
|
||||
@@ -587,13 +619,13 @@ public final class ContainerBuilder {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
container.callInContext(new ContainerImpl.ContextualCallable<Void>() {
|
||||
public Void call(InternalContext context) {
|
||||
for (InternalFactory<?> factory : initializableFactories) {
|
||||
Initializable instance = (Initializable) factory.create(context);
|
||||
instance.init();
|
||||
}
|
||||
return null;
|
||||
for (InternalFactory<?> factory : earlyInitializableFactories) {
|
||||
factory.create(context);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -1,23 +1,18 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2006 Google Inc.
|
||||
*
|
||||
* <p>
|
||||
* 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
|
||||
* </p>
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* <p>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
* </p>
|
||||
*/
|
||||
|
||||
package com.opensymphony.xwork2.inject;
|
||||
|
||||
import com.opensymphony.xwork2.inject.util.ReferenceCache;
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Copyright 2002-2006,2009 The Apache Software Foundation.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.inject;
|
||||
|
||||
/**
|
||||
* A marking interface that will tell CI to initialise the bean when instating the whole objects' graph
|
||||
*/
|
||||
public interface EarlyInitializable extends Initializable {
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2006 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.opensymphony.xwork2.inject;
|
||||
|
||||
/**
|
||||
@@ -23,12 +22,20 @@ package com.opensymphony.xwork2.inject;
|
||||
*/
|
||||
public interface Factory<T> {
|
||||
|
||||
/**
|
||||
* Creates an object to be injected.
|
||||
*
|
||||
* @param context of this injection
|
||||
* @return instance to be injected
|
||||
* @throws Exception if unable to create object
|
||||
*/
|
||||
T create(Context context) throws Exception;
|
||||
/**
|
||||
* Creates an object to be injected.
|
||||
*
|
||||
* @param context of this injection
|
||||
* @return instance to be injected
|
||||
* @throws Exception if unable to create object
|
||||
*/
|
||||
T create(Context context) throws Exception;
|
||||
|
||||
/**
|
||||
* Returns a class of <T>
|
||||
*
|
||||
* @return class of the object
|
||||
*/
|
||||
Class<? extends T> type();
|
||||
|
||||
}
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.inject;
|
||||
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
|
||||
class InitializableFactory<T> implements InternalFactory<T> {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(InitializableFactory.class);
|
||||
|
||||
private InternalFactory<T> internalFactory;
|
||||
|
||||
private InitializableFactory(InternalFactory<T> internalFactory) {
|
||||
this.internalFactory = internalFactory;
|
||||
}
|
||||
|
||||
public static <T> InternalFactory<T> wrapIfNeeded(InternalFactory<T> internalFactory) {
|
||||
if (Initializable.class.isAssignableFrom(internalFactory.type())) {
|
||||
return new InitializableFactory<>(internalFactory);
|
||||
}
|
||||
return internalFactory;
|
||||
}
|
||||
|
||||
@Override
|
||||
public T create(InternalContext context) {
|
||||
T instance = internalFactory.create(context);
|
||||
if (Initializable.class.isAssignableFrom(instance.getClass())) {
|
||||
Initializable.class.cast(instance).init();
|
||||
} else {
|
||||
LOG.error("Class {} is not marked as {}!", internalFactory.getClass().getName(), Initializable.class.getName());
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return internalFactory.type();
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
/**
|
||||
/*
|
||||
* Copyright (C) 2006 Google Inc.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@@ -13,7 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package com.opensymphony.xwork2.inject;
|
||||
|
||||
import java.io.Serializable;
|
||||
@@ -25,11 +24,19 @@ import java.io.Serializable;
|
||||
*/
|
||||
interface InternalFactory<T> extends Serializable {
|
||||
|
||||
/**
|
||||
* Creates an object to be injected.
|
||||
*
|
||||
* @param context of this injection
|
||||
* @return instance to be injected
|
||||
*/
|
||||
T create(InternalContext context);
|
||||
/**
|
||||
* Creates an object to be injected.
|
||||
*
|
||||
* @param context of this injection
|
||||
* @return instance to be injected
|
||||
*/
|
||||
T create(InternalContext context);
|
||||
|
||||
/**
|
||||
* Returns a class of <T>
|
||||
*
|
||||
* @return class of the object
|
||||
*/
|
||||
Class<? extends T> type();
|
||||
|
||||
}
|
||||
|
||||
@@ -33,7 +33,7 @@ public enum Scope {
|
||||
@Override
|
||||
<T> InternalFactory<? extends T> scopeFactory(Class<T> type, String name,
|
||||
InternalFactory<? extends T> factory) {
|
||||
return factory;
|
||||
return InitializableFactory.wrapIfNeeded(factory);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -49,12 +49,17 @@ public enum Scope {
|
||||
public T create(InternalContext context) {
|
||||
synchronized (context.getContainer()) {
|
||||
if (instance == null) {
|
||||
instance = factory.create(context);
|
||||
instance = InitializableFactory.wrapIfNeeded(factory).create(context);
|
||||
}
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return factory.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return factory.toString();
|
||||
@@ -83,12 +88,17 @@ public enum Scope {
|
||||
public T create(final InternalContext context) {
|
||||
T t = threadLocal.get();
|
||||
if (t == null) {
|
||||
t = factory.create(context);
|
||||
t = InitializableFactory.wrapIfNeeded(factory).create(context);
|
||||
threadLocal.set(t);
|
||||
}
|
||||
return t;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return factory.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return factory.toString();
|
||||
@@ -114,6 +124,11 @@ public enum Scope {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return factory.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return factory.toString();
|
||||
@@ -139,6 +154,11 @@ public enum Scope {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return factory.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return factory.toString();
|
||||
@@ -164,6 +184,11 @@ public enum Scope {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class<? extends T> type() {
|
||||
return factory.type();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return factory.toString();
|
||||
@@ -176,7 +201,7 @@ public enum Scope {
|
||||
final InternalFactory<? extends T> factory) {
|
||||
return new Callable<T>() {
|
||||
public T call() throws Exception {
|
||||
return factory.create(context);
|
||||
return InitializableFactory.wrapIfNeeded(factory).create(context);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
+4
-2
@@ -118,11 +118,13 @@ public class ParameterFilterInterceptor extends AbstractInterceptor {
|
||||
for (String param : parameters.keySet()) {
|
||||
boolean currentAllowed = !isDefaultBlock();
|
||||
|
||||
for (String currRule : includesExcludesMap.keySet()) {
|
||||
for (Map.Entry<String, Boolean> entry : includesExcludesMap.entrySet()) {
|
||||
String currRule = entry.getKey();
|
||||
|
||||
if (param.startsWith(currRule) &&
|
||||
(param.length() == currRule.length() || isPropertySeparator(param.charAt(currRule.length())))
|
||||
) {
|
||||
currentAllowed = includesExcludesMap.get(currRule);
|
||||
currentAllowed = entry.getValue();
|
||||
}
|
||||
}
|
||||
if (!currentAllowed) {
|
||||
|
||||
@@ -172,10 +172,11 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
acceptableParameters = new TreeMap<>();
|
||||
}
|
||||
|
||||
for (String name : params.keySet()) {
|
||||
Parameter parameter = params.get(name);
|
||||
if (isAcceptableParameter(name, action)) {
|
||||
acceptableParameters.put(name, parameter);
|
||||
for (Map.Entry<String, Parameter> entry : params.entrySet()) {
|
||||
String parameterName = entry.getKey();
|
||||
|
||||
if (isAcceptableParameter(parameterName, action)) {
|
||||
acceptableParameters.put(parameterName, entry.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -270,10 +271,10 @@ public class ParametersInterceptor extends MethodFilterInterceptor {
|
||||
}
|
||||
|
||||
StringBuilder logEntry = new StringBuilder();
|
||||
for (String name : parameters.keySet()) {
|
||||
logEntry.append(String.valueOf(name));
|
||||
for (Map.Entry<String, Parameter> entry : parameters.entrySet()) {
|
||||
logEntry.append(entry.getKey());
|
||||
logEntry.append(" => ");
|
||||
logEntry.append(parameters.get(name).getValue());
|
||||
logEntry.append(entry.getValue().getValue());
|
||||
logEntry.append(" ");
|
||||
}
|
||||
|
||||
|
||||
@@ -124,12 +124,4 @@ public class MockActionInvocation implements ActionInvocation {
|
||||
public void init(ActionProxy proxy) {
|
||||
}
|
||||
|
||||
public ActionInvocation serialize() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ActionInvocation deserialize(ActionContext actionContext) {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+11
-4
@@ -28,6 +28,7 @@ import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
|
||||
import ognl.ListPropertyAccessor;
|
||||
import ognl.OgnlException;
|
||||
import ognl.PropertyAccessor;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -49,12 +50,18 @@ public class XWorkListPropertyAccessor extends ListPropertyAccessor {
|
||||
private ObjectTypeDeterminer objectTypeDeterminer;
|
||||
private OgnlUtil ognlUtil;
|
||||
private int autoGrowCollectionLimit = 255;
|
||||
|
||||
|
||||
@Deprecated()
|
||||
@Inject(value = "xwork.autoGrowCollectionLimit", required = false)
|
||||
public void setAutoGrowCollectionLimit(String value) {
|
||||
this.autoGrowCollectionLimit = Integer.valueOf(value);
|
||||
}
|
||||
public void setDeprecatedAutoGrowCollectionLimit(String value) {
|
||||
this.autoGrowCollectionLimit = Integer.valueOf(value);
|
||||
}
|
||||
|
||||
@Inject(value = StrutsConstants.STRUTS_OGNL_AUTO_GROWTH_COLLECTION_LIMIT, required = false)
|
||||
public void setAutoGrowCollectionLimit(String value) {
|
||||
this.autoGrowCollectionLimit = Integer.parseInt(value);
|
||||
}
|
||||
|
||||
@Inject("java.util.Collection")
|
||||
public void setXWorkCollectionPropertyAccessor(PropertyAccessor acc) {
|
||||
this._sAcc = (XWorkCollectionPropertyAccessor) acc;
|
||||
|
||||
@@ -18,9 +18,12 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2.util;
|
||||
|
||||
import org.apache.commons.lang3.ClassUtils;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.regex.Matcher;
|
||||
@@ -129,7 +132,7 @@ public class AnnotationUtils {
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the annotation on the given class or the package of the class. This searchs up the
|
||||
* Returns the annotation on the given class or the package of the class. This searches up the
|
||||
* class hierarchy and the package hierarchy for the closest match.
|
||||
*
|
||||
* @param <T> class type
|
||||
@@ -154,4 +157,36 @@ public class AnnotationUtils {
|
||||
|
||||
return ann;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of the annotation on the given class or the package of the class.
|
||||
* This searches up the class hierarchy and the package hierarchy.
|
||||
*
|
||||
* @param <T> class type
|
||||
* @param clazz The class to search for the annotation.
|
||||
* @param annotationClass The Class of the annotation.
|
||||
* @return List of the annotations or an empty list.
|
||||
*/
|
||||
public static <T extends Annotation> List<T> findAnnotations(Class<?> clazz, Class<T> annotationClass) {
|
||||
List<T> anns = new ArrayList<>();
|
||||
|
||||
List<Class<?>> classes = new ArrayList<>();
|
||||
classes.add(clazz);
|
||||
|
||||
classes.addAll(ClassUtils.getAllSuperclasses(clazz));
|
||||
classes.addAll(ClassUtils.getAllInterfaces(clazz));
|
||||
for (Class<?> aClass : classes) {
|
||||
T ann = aClass.getAnnotation(annotationClass);
|
||||
if (ann != null) {
|
||||
anns.add(ann);
|
||||
}
|
||||
|
||||
ann = aClass.getPackage().getAnnotation(annotationClass);
|
||||
if (ann != null) {
|
||||
anns.add(ann);
|
||||
}
|
||||
}
|
||||
|
||||
return anns;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -171,8 +171,8 @@ public class GlobalLocalizedTextProvider extends AbstractLocalizedTextProvider {
|
||||
|
||||
indexedTextName = aTextName;
|
||||
|
||||
while ((i = indexedTextName.indexOf("[", i + 1)) != -1) {
|
||||
int j = indexedTextName.indexOf("]", i);
|
||||
while ((i = indexedTextName.indexOf('[', i + 1)) != -1) {
|
||||
int j = indexedTextName.indexOf(']', i);
|
||||
String a = indexedTextName.substring(0, i);
|
||||
String b = indexedTextName.substring(j);
|
||||
indexedTextName = a + "[*" + b;
|
||||
|
||||
@@ -232,8 +232,8 @@ public class StrutsLocalizedTextProvider extends AbstractLocalizedTextProvider {
|
||||
|
||||
indexedTextName = aTextName;
|
||||
|
||||
while ((i = indexedTextName.indexOf("[", i + 1)) != -1) {
|
||||
int j = indexedTextName.indexOf("]", i);
|
||||
while ((i = indexedTextName.indexOf('[', i + 1)) != -1) {
|
||||
int j = indexedTextName.indexOf(']', i);
|
||||
String a = indexedTextName.substring(0, i);
|
||||
String b = indexedTextName.substring(j);
|
||||
indexedTextName = a + "[*" + b;
|
||||
@@ -293,14 +293,14 @@ public class StrutsLocalizedTextProvider extends AbstractLocalizedTextProvider {
|
||||
}
|
||||
|
||||
// see if it's a child property
|
||||
int idx = aTextName.indexOf(".");
|
||||
int idx = aTextName.indexOf('.');
|
||||
|
||||
if (idx != -1) {
|
||||
String newKey = null;
|
||||
String prop = null;
|
||||
|
||||
if (aTextName.startsWith(XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX)) {
|
||||
idx = aTextName.indexOf(".", XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX.length());
|
||||
idx = aTextName.indexOf('.', XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX.length());
|
||||
|
||||
if (idx != -1) {
|
||||
prop = aTextName.substring(XWorkConverter.CONVERSION_ERROR_PROPERTY_PREFIX.length(), idx);
|
||||
|
||||
@@ -189,7 +189,7 @@ public interface ClassFinder {
|
||||
}
|
||||
|
||||
public String getPackageName(){
|
||||
return name.indexOf(".") > 0 ? name.substring(0, name.lastIndexOf(".")) : "" ;
|
||||
return name.indexOf('.') > 0 ? name.substring(0, name.lastIndexOf('.')) : "" ;
|
||||
}
|
||||
|
||||
public List<MethodInfo> getConstructors() {
|
||||
|
||||
@@ -37,11 +37,9 @@ public class JarEntryRevision extends Revision {
|
||||
private long lastModified;
|
||||
|
||||
public static Revision build(URL fileUrl, FileManager fileManager) {
|
||||
// File within a Jar
|
||||
// Find separator index of jar filename and filename within jar
|
||||
JarURLConnection conn = null;
|
||||
try {
|
||||
conn = (JarURLConnection) fileUrl.openConnection();
|
||||
conn = StrutsJarURLConnection.openConnection(fileUrl);
|
||||
conn.setUseCaches(false);
|
||||
URL url = fileManager.normalizeToFileProtocol(fileUrl);
|
||||
if (url != null) {
|
||||
@@ -75,7 +73,7 @@ public class JarEntryRevision extends Revision {
|
||||
JarURLConnection conn = null;
|
||||
long lastLastModified = lastModified;
|
||||
try {
|
||||
conn = (JarURLConnection) jarFileURL.openConnection();
|
||||
conn = StrutsJarURLConnection.openConnection(jarFileURL);
|
||||
conn.setUseCaches(false);
|
||||
lastLastModified = conn.getJarEntry().getTime();
|
||||
} catch (IOException ignored) {
|
||||
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.util.fs;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.JarURLConnection;
|
||||
import java.net.MalformedURLException;
|
||||
import java.net.URL;
|
||||
import java.net.URLConnection;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.StandardCopyOption;
|
||||
import java.security.AccessController;
|
||||
import java.security.PrivilegedActionException;
|
||||
import java.security.PrivilegedExceptionAction;
|
||||
import java.util.jar.JarFile;
|
||||
|
||||
/**
|
||||
* WW-4901 Decouples from underlying implementation of {@link URL#openConnection()}
|
||||
* e.g. from IBM WebSphere com.ibm.ws.classloader.Handler$ClassLoaderURLConnection
|
||||
* @since 2.5.15
|
||||
*/
|
||||
class StrutsJarURLConnection extends JarURLConnection {
|
||||
private JarFile jarFile;
|
||||
|
||||
private StrutsJarURLConnection(URL url) throws MalformedURLException {
|
||||
super(url);
|
||||
}
|
||||
|
||||
@Override
|
||||
public JarFile getJarFile() throws IOException {
|
||||
connect();
|
||||
return jarFile;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void connect() throws IOException {
|
||||
if (connected) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (final InputStream in = getJarFileURL().openConnection().getInputStream()) {
|
||||
jarFile = AccessController.doPrivileged(
|
||||
new PrivilegedExceptionAction<JarFile>() {
|
||||
public JarFile run() throws IOException {
|
||||
Path tmpFile = Files.createTempFile("jar_cache", null);
|
||||
try {
|
||||
Files.copy(in, tmpFile, StandardCopyOption.REPLACE_EXISTING);
|
||||
JarFile jarFile = new JarFile(tmpFile.toFile(), true, JarFile.OPEN_READ);
|
||||
tmpFile.toFile().deleteOnExit();
|
||||
return jarFile;
|
||||
} catch (Throwable thr) {
|
||||
try {
|
||||
Files.delete(tmpFile);
|
||||
} catch (IOException ioe) {
|
||||
thr.addSuppressed(ioe);
|
||||
}
|
||||
throw thr;
|
||||
} finally {
|
||||
in.close();
|
||||
}
|
||||
}
|
||||
});
|
||||
connected = true;
|
||||
} catch (PrivilegedActionException pae) {
|
||||
throw (IOException) pae.getException();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static JarURLConnection openConnection(URL url) throws IOException {
|
||||
URLConnection conn = url.openConnection();
|
||||
if (conn instanceof JarURLConnection) {
|
||||
return (JarURLConnection) conn;
|
||||
} else {
|
||||
try {
|
||||
conn.getInputStream().close();
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
StrutsJarURLConnection result = new StrutsJarURLConnection(url);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -22,6 +22,7 @@ import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.ObjectFactory;
|
||||
import com.opensymphony.xwork2.XWorkException;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.inject.Initializable;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.ClassLoaderUtil;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
@@ -44,7 +45,7 @@ import java.util.zip.ZipInputStream;
|
||||
* @author Jason Carreira
|
||||
* @author James House
|
||||
*/
|
||||
public class DefaultValidatorFactory implements ValidatorFactory {
|
||||
public class DefaultValidatorFactory implements ValidatorFactory, Initializable {
|
||||
|
||||
protected Map<String, String> validators = new HashMap<>();
|
||||
private static Logger LOG = LogManager.getLogger(DefaultValidatorFactory.class);
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2.validator;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Initializable;
|
||||
|
||||
/**
|
||||
* ValidatorFactory
|
||||
*
|
||||
@@ -227,7 +225,7 @@ import com.opensymphony.xwork2.inject.Initializable;
|
||||
* @author Jason Carreira
|
||||
* @author James House
|
||||
*/
|
||||
public interface ValidatorFactory extends Initializable {
|
||||
public interface ValidatorFactory {
|
||||
|
||||
/**
|
||||
* Get a Validator that matches the given configuration.
|
||||
|
||||
@@ -328,4 +328,6 @@ public final class StrutsConstants {
|
||||
public static final String STRUTS_LOCALIZED_TEXT_PROVIDER = "struts.localizedTextProvider";
|
||||
|
||||
public static final String STRUTS_DISALLOW_PROXY_MEMBER_ACCESS = "struts.disallowProxyMemberAccess";
|
||||
|
||||
public static final String STRUTS_OGNL_AUTO_GROWTH_COLLECTION_LIMIT = "struts.ognl.autoGrowthCollectionLimit";
|
||||
}
|
||||
|
||||
@@ -80,14 +80,17 @@ public class Anchor extends ClosingUIBean {
|
||||
urlProvider.setHttpServletResponse(response);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getDefaultOpenTemplate() {
|
||||
return OPEN_TEMPLATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected String getDefaultTemplate() {
|
||||
return TEMPLATE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean usesBody() {
|
||||
return true;
|
||||
}
|
||||
@@ -96,16 +99,17 @@ public class Anchor extends ClosingUIBean {
|
||||
protected void evaluateExtraParams() {
|
||||
super.evaluateExtraParams();
|
||||
|
||||
if (href != null)
|
||||
if (href != null) {
|
||||
addParameter("href", ensureAttributeSafelyNotEscaped(findString(href)));
|
||||
else {
|
||||
} else {
|
||||
//no href, build it from URL attributes
|
||||
StringWriter sw = new StringWriter();
|
||||
urlRenderer.beforeRenderUrl(urlProvider);
|
||||
urlRenderer.renderUrl(sw, urlProvider);
|
||||
String builtHref = sw.toString();
|
||||
if (StringUtils.isNotEmpty(builtHref))
|
||||
if (StringUtils.isNotEmpty(builtHref)) {
|
||||
addParameter("href", ensureAttributeSafelyNotEscaped(builtHref));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,10 +119,10 @@ public class Anchor extends ClosingUIBean {
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setUrlRenderer(UrlRenderer urlRenderer) {
|
||||
urlProvider.setUrlRenderer(urlRenderer);
|
||||
public void setUrlRenderer(UrlRenderer urlRenderer) {
|
||||
urlProvider.setUrlRenderer(urlRenderer);
|
||||
this.urlRenderer = urlRenderer;
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(required=false)
|
||||
public void setExtraParameterProvider(ExtraParameterProvider provider) {
|
||||
@@ -135,6 +139,7 @@ public class Anchor extends ClosingUIBean {
|
||||
/**
|
||||
* Overrides to be able to render body in a template rather than always before the template
|
||||
*/
|
||||
@Override
|
||||
public boolean end(Writer writer, String body) {
|
||||
this.processingTagBody = false;
|
||||
evaluateParams();
|
||||
@@ -143,15 +148,14 @@ public class Anchor extends ClosingUIBean {
|
||||
mergeTemplate(writer, buildTemplateName(template, getDefaultTemplate()));
|
||||
} catch (Exception e) {
|
||||
LOG.error("error when rendering", e);
|
||||
}
|
||||
finally {
|
||||
} finally {
|
||||
popComponentStack();
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public void addParameter(String key, Object value) {
|
||||
/*
|
||||
the parameters added by this method are used in the template. this method is also
|
||||
@@ -160,8 +164,9 @@ public class Anchor extends ClosingUIBean {
|
||||
*/
|
||||
if (processingTagBody) {
|
||||
this.urlParameters.put(key, value);
|
||||
} else
|
||||
} else {
|
||||
super.addParameter(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -173,8 +178,9 @@ public class Anchor extends ClosingUIBean {
|
||||
*/
|
||||
if (processingTagBody) {
|
||||
this.urlParameters.putAll(params);
|
||||
} else
|
||||
} else {
|
||||
super.addAllParameters(params);
|
||||
}
|
||||
}
|
||||
|
||||
public UrlProvider getUrlProvider() {
|
||||
@@ -196,6 +202,7 @@ public class Anchor extends ClosingUIBean {
|
||||
urlProvider.setScheme(scheme);
|
||||
}
|
||||
|
||||
@Override
|
||||
@StrutsTagAttribute(description = "The target value to use, if not using action")
|
||||
public void setValue(String value) {
|
||||
urlProvider.setValue(value);
|
||||
|
||||
@@ -30,17 +30,17 @@ import java.util.Map;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.struts2.dispatcher.PrepareOperations;
|
||||
import org.apache.struts2.views.annotations.StrutsTag;
|
||||
import org.apache.struts2.StrutsException;
|
||||
|
||||
@StrutsTag(name="debug", tldTagClass="org.apache.struts2.views.jsp.ui.DebugTag",
|
||||
description="Prints debugging information")
|
||||
description="Prints debugging information (Only if 'struts.devMode' is enabled)")
|
||||
public class Debug extends UIBean {
|
||||
public static final String TEMPLATE = "debug";
|
||||
|
||||
|
||||
protected ReflectionProvider reflectionProvider;
|
||||
|
||||
|
||||
|
||||
public Debug(ValueStack stack, HttpServletRequest request, HttpServletResponse response) {
|
||||
super(stack, request, response);
|
||||
@@ -50,7 +50,7 @@ public class Debug extends UIBean {
|
||||
public void setReflectionProvider(ReflectionProvider prov) {
|
||||
this.reflectionProvider = prov;
|
||||
}
|
||||
|
||||
|
||||
protected String getDefaultTemplate() {
|
||||
return TEMPLATE;
|
||||
}
|
||||
@@ -58,25 +58,40 @@ public class Debug extends UIBean {
|
||||
public boolean start(Writer writer) {
|
||||
boolean result = super.start(writer);
|
||||
|
||||
ValueStack stack = getStack();
|
||||
Iterator iter = stack.getRoot().iterator();
|
||||
List stackValues = new ArrayList(stack.getRoot().size());
|
||||
while (iter.hasNext()) {
|
||||
Object o = iter.next();
|
||||
Map values;
|
||||
try {
|
||||
values = reflectionProvider.getBeanMap(o);
|
||||
} catch (Exception e) {
|
||||
throw new StrutsException("Caught an exception while getting the property values of " + o, e);
|
||||
if (showDebug()) {
|
||||
ValueStack stack = getStack();
|
||||
Iterator iter = stack.getRoot().iterator();
|
||||
List stackValues = new ArrayList(stack.getRoot().size());
|
||||
while (iter.hasNext()) {
|
||||
Object o = iter.next();
|
||||
Map values;
|
||||
try {
|
||||
values = reflectionProvider.getBeanMap(o);
|
||||
} catch (Exception e) {
|
||||
throw new StrutsException("Caught an exception while getting the property values of " + o, e);
|
||||
}
|
||||
stackValues.add(new DebugMapEntry(o.getClass().getName(), values));
|
||||
}
|
||||
stackValues.add(new DebugMapEntry(o.getClass().getName(), values));
|
||||
|
||||
addParameter("stackValues", stackValues);
|
||||
}
|
||||
|
||||
addParameter("stackValues", stackValues);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean end(Writer writer, String body) {
|
||||
if (showDebug()) {
|
||||
return super.end(writer, body);
|
||||
} else {
|
||||
popComponentStack();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean showDebug() {
|
||||
return (devMode || Boolean.TRUE == PrepareOperations.getDevModeOverride());
|
||||
}
|
||||
|
||||
private static class DebugMapEntry implements Map.Entry {
|
||||
private Object key;
|
||||
private Object value;
|
||||
|
||||
@@ -89,8 +89,8 @@ public class ServletUrlRenderer implements UrlRenderer {
|
||||
|
||||
// We don't include the request parameters cause they would have been
|
||||
// prioritised before this [in start(Writer) method]
|
||||
if (_value != null && _value.indexOf("?") > 0) {
|
||||
_value = _value.substring(0, _value.indexOf("?"));
|
||||
if (_value != null && _value.indexOf('?') > 0) {
|
||||
_value = _value.substring(0, _value.indexOf('?'));
|
||||
}
|
||||
result = urlHelper.buildUrl(_value, urlComponent.getHttpServletRequest(), urlComponent.getHttpServletResponse(), urlComponent.getParameters(), scheme, urlComponent.isIncludeContext(), urlComponent.isEncode(), urlComponent.isForceAddSchemeHostAndPort(), urlComponent.isEscapeAmp());
|
||||
}
|
||||
@@ -150,10 +150,10 @@ public class ServletUrlRenderer implements UrlRenderer {
|
||||
}
|
||||
|
||||
Map actionParams = null;
|
||||
if (action != null && action.indexOf("?") > 0) {
|
||||
String queryString = action.substring(action.indexOf("?") + 1);
|
||||
if (action != null && action.indexOf('?') > 0) {
|
||||
String queryString = action.substring(action.indexOf('?') + 1);
|
||||
actionParams = urlHelper.parseQueryString(queryString, false);
|
||||
action = action.substring(0, action.indexOf("?"));
|
||||
action = action.substring(0, action.indexOf('?'));
|
||||
}
|
||||
|
||||
ActionMapping nameMapping = actionMapper.getMappingFromActionName(action);
|
||||
@@ -322,7 +322,7 @@ public class ServletUrlRenderer implements UrlRenderer {
|
||||
// where the parameters specified in value attribute takes priority.
|
||||
|
||||
if (StringUtils.contains(value, "?")) {
|
||||
String queryString = value.substring(value.indexOf("?") + 1);
|
||||
String queryString = value.substring(value.indexOf('?') + 1);
|
||||
|
||||
mergedParams = urlHelper.parseQueryString(queryString, false);
|
||||
for (Map.Entry<String, Object> entry : contextParameters.entrySet()) {
|
||||
|
||||
@@ -528,6 +528,7 @@ public abstract class UIBean extends Component {
|
||||
this.templateEngineManager = mgr;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean end(Writer writer, String body) {
|
||||
evaluateParams();
|
||||
try {
|
||||
@@ -883,7 +884,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("[\\/\\.\\[\\]]", "_");
|
||||
@@ -930,7 +931,7 @@ public abstract class UIBean extends Component {
|
||||
form.addParameter("customOnsubmitEnabled", Boolean.TRUE);
|
||||
} else {
|
||||
if (LOG.isWarnEnabled()) {
|
||||
LOG.warn("Cannot find an Ancestor form, custom onsubmit is NOT enabled");
|
||||
LOG.warn("Cannot find an Ancestor form, custom onsubmit is NOT enabled");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1240,27 +1241,30 @@ public abstract class UIBean extends Component {
|
||||
this.tooltipIconPath = tooltipIconPath;
|
||||
}
|
||||
|
||||
public void setDynamicAttributes(Map<String, Object> tagDynamicAttributes) {
|
||||
for (String key : tagDynamicAttributes.keySet()) {
|
||||
public void setDynamicAttributes(Map<String, Object> tagDynamicAttributes) {
|
||||
for (Map.Entry<String, Object> entry : tagDynamicAttributes.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
|
||||
if (!isValidTagAttribute(key)) {
|
||||
dynamicAttributes.put(key, tagDynamicAttributes.get(key));
|
||||
dynamicAttributes.put(key, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
/**
|
||||
* supports dynamic attributes for freemarker ui tags
|
||||
* @see https://issues.apache.org/jira/browse/WW-3174
|
||||
@Override
|
||||
/**
|
||||
* supports dynamic attributes for freemarker ui tags
|
||||
* @see https://issues.apache.org/jira/browse/WW-3174
|
||||
* @see https://issues.apache.org/jira/browse/WW-4166
|
||||
*/
|
||||
*/
|
||||
public void copyParams(Map params) {
|
||||
super.copyParams(params);
|
||||
for (Object o : params.entrySet()) {
|
||||
Map.Entry entry = (Map.Entry) o;
|
||||
String key = (String) entry.getKey();
|
||||
if(!isValidTagAttribute(key) && !key.equals("dynamicAttributes"))
|
||||
if (!isValidTagAttribute(key) && !key.equals("dynamicAttributes")) {
|
||||
dynamicAttributes.put(key, entry.getValue());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -28,26 +28,26 @@ import java.io.Writer;
|
||||
*
|
||||
*/
|
||||
public interface UrlRenderer {
|
||||
|
||||
/**
|
||||
* Preprocessing step
|
||||
* @param provider The {@link UrlProvider} component that "owns" this renderer.
|
||||
*/
|
||||
void beforeRenderUrl(UrlProvider provider);
|
||||
|
||||
/**
|
||||
* Render a URL.
|
||||
* @param writer A writer that the implementation can use to write the result to.
|
||||
* @param provider The {@link UrlProvider} component that "owns" this renderer.
|
||||
*/
|
||||
void renderUrl(Writer writer, UrlProvider provider);
|
||||
|
||||
/**
|
||||
* Render a Form URL.
|
||||
* @param formComponent The {@link Form} component that "owns" this renderer.
|
||||
*/
|
||||
void renderFormUrl(Form formComponent);
|
||||
|
||||
void setActionMapper(ActionMapper actionMapper);
|
||||
/**
|
||||
* Preprocessing step
|
||||
* @param provider The {@link UrlProvider} component that "owns" this renderer.
|
||||
*/
|
||||
void beforeRenderUrl(UrlProvider provider);
|
||||
|
||||
/**
|
||||
* Render a URL.
|
||||
* @param writer A writer that the implementation can use to write the result to.
|
||||
* @param provider The {@link UrlProvider} component that "owns" this renderer.
|
||||
*/
|
||||
void renderUrl(Writer writer, UrlProvider provider);
|
||||
|
||||
/**
|
||||
* Render a Form URL.
|
||||
* @param formComponent The {@link Form} component that "owns" this renderer.
|
||||
*/
|
||||
void renderFormUrl(Form formComponent);
|
||||
|
||||
void setActionMapper(ActionMapper actionMapper);
|
||||
|
||||
}
|
||||
|
||||
@@ -142,7 +142,7 @@ public abstract class BaseTemplateEngine implements TemplateEngine {
|
||||
|
||||
protected String getFinalTemplateName(Template template) {
|
||||
String t = template.toString();
|
||||
if (t.indexOf(".") <= 0) {
|
||||
if (t.indexOf('.') <= 0) {
|
||||
return t + "." + getSuffix();
|
||||
}
|
||||
return t;
|
||||
|
||||
@@ -113,5 +113,10 @@ public abstract class AbstractBeanSelectionProvider implements BeanSelectionProv
|
||||
throw new ConfigurationException("Unable to load bean "+type.getName()+" ("+name+")");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return type;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -90,6 +90,9 @@ public class StrutsXmlConfigurationProvider extends XmlConfigurationProvider {
|
||||
public ServletContext create(Context context) throws Exception {
|
||||
return servletContext;
|
||||
}
|
||||
public Class<? extends ServletContext> type() {
|
||||
return servletContext.getClass();
|
||||
}
|
||||
});
|
||||
}
|
||||
super.register(containerBuilder, props);
|
||||
|
||||
@@ -163,8 +163,8 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
}
|
||||
}
|
||||
if (!allowSlashesInActionNames && !allowActionCrossNamespaceAccess) {
|
||||
if (actionName.lastIndexOf("/") != -1) {
|
||||
actionName = actionName.substring(actionName.lastIndexOf("/") + 1);
|
||||
if (actionName.lastIndexOf('/') != -1) {
|
||||
actionName = actionName.substring(actionName.lastIndexOf('/') + 1);
|
||||
}
|
||||
}
|
||||
mapping.setName(actionName);
|
||||
@@ -271,7 +271,7 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
ActionMapping mapping = new ActionMapping();
|
||||
String uri = RequestUtils.getUri(request);
|
||||
|
||||
int indexOfSemicolon = uri.indexOf(";");
|
||||
int indexOfSemicolon = uri.indexOf(';');
|
||||
uri = (indexOfSemicolon > -1) ? uri.substring(0, indexOfSemicolon) : uri;
|
||||
|
||||
uri = dropExtension(uri, mapping);
|
||||
@@ -291,7 +291,7 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
if (allowDynamicMethodCalls) {
|
||||
// handle "name!method" convention.
|
||||
String name = mapping.getName();
|
||||
int exclamation = name.lastIndexOf("!");
|
||||
int exclamation = name.lastIndexOf('!');
|
||||
if (exclamation != -1) {
|
||||
mapping.setName(name.substring(0, exclamation));
|
||||
|
||||
@@ -341,7 +341,7 @@ public class DefaultActionMapper implements ActionMapper {
|
||||
*/
|
||||
protected void parseNameAndNamespace(String uri, ActionMapping mapping, ConfigurationManager configManager) {
|
||||
String namespace, name;
|
||||
int lastSlash = uri.lastIndexOf("/");
|
||||
int lastSlash = uri.lastIndexOf('/');
|
||||
if (lastSlash == -1) {
|
||||
namespace = "";
|
||||
name = uri;
|
||||
|
||||
+2
-2
@@ -131,8 +131,8 @@ public abstract class AbstractMultiPartRequest implements MultiPartRequest {
|
||||
protected String getCanonicalName(final String originalFileName) {
|
||||
String fileName = originalFileName;
|
||||
|
||||
int forwardSlash = fileName.lastIndexOf("/");
|
||||
int backwardSlash = fileName.lastIndexOf("\\");
|
||||
int forwardSlash = fileName.lastIndexOf('/');
|
||||
int backwardSlash = fileName.lastIndexOf('\\');
|
||||
if (forwardSlash != -1 && forwardSlash > backwardSlash) {
|
||||
fileName = fileName.substring(forwardSlash + 1, fileName.length());
|
||||
} else {
|
||||
|
||||
+2
-2
@@ -60,8 +60,8 @@ public class JakartaStreamMultiPartRequest extends AbstractMultiPartRequest {
|
||||
*/
|
||||
public void cleanUp() {
|
||||
LOG.debug("Performing File Upload temporary storage cleanup.");
|
||||
for (String fieldName : fileInfos.keySet()) {
|
||||
for (FileInfo fileInfo : fileInfos.get(fieldName)) {
|
||||
for (List<FileInfo> fileInfoList : fileInfos.values()) {
|
||||
for (FileInfo fileInfo : fileInfoList) {
|
||||
File file = fileInfo.getFile();
|
||||
LOG.debug("Deleting file '{}'.", file.getName());
|
||||
if (!file.delete()) {
|
||||
|
||||
@@ -22,13 +22,17 @@ import com.opensymphony.xwork2.ActionProxy;
|
||||
import com.opensymphony.xwork2.ActionProxyFactory;
|
||||
import com.opensymphony.xwork2.DefaultActionProxyFactory;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.inject.Initializable;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import org.apache.logging.log4j.LogManager;
|
||||
import org.apache.logging.log4j.Logger;
|
||||
import org.apache.struts2.StrutsConstants;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: description -->
|
||||
@@ -55,38 +59,37 @@ import java.util.Map;
|
||||
* </pre>
|
||||
* <!-- END SNIPPET: description -->
|
||||
*/
|
||||
public class PrefixBasedActionProxyFactory extends DefaultActionProxyFactory {
|
||||
public class PrefixBasedActionProxyFactory extends StrutsActionProxyFactory implements Initializable {
|
||||
|
||||
private static final Logger LOG = LogManager.getLogger(PrefixBasedActionProxyFactory.class);
|
||||
|
||||
private Map<String, ActionProxyFactory> actionProxyFactories = new HashMap<>();
|
||||
private ActionProxyFactory defaultFactory;
|
||||
private Set<String> prefixes = new HashSet<>();
|
||||
|
||||
@Inject
|
||||
public void setContainer(Container container) {
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
@Inject(StrutsConstants.STRUTS_ACTIONPROXYFACTORY)
|
||||
public void setActionProxyFactory(ActionProxyFactory factory) {
|
||||
this.defaultFactory = factory;
|
||||
}
|
||||
|
||||
@Inject(StrutsConstants.PREFIX_BASED_MAPPER_CONFIGURATION)
|
||||
public void setPrefixBasedActionProxyFactories(String list) {
|
||||
if (list != null) {
|
||||
String[] factories = list.split(",");
|
||||
for (String factory : factories) {
|
||||
String[] thisFactory = factory.split(":");
|
||||
if (thisFactory.length == 2) {
|
||||
String factoryPrefix = thisFactory[0].trim();
|
||||
String factoryName = thisFactory[1].trim();
|
||||
ActionProxyFactory obj = container.getInstance(ActionProxyFactory.class, factoryName);
|
||||
if (obj != null) {
|
||||
actionProxyFactories.put(factoryPrefix, obj);
|
||||
} else {
|
||||
LOG.warn("Invalid PrefixBasedActionProxyFactory config entry: [{}]", factory);
|
||||
}
|
||||
prefixes = new HashSet<>(Arrays.asList(list.split(",")));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
for (String factory : prefixes) {
|
||||
String[] thisFactory = factory.split(":");
|
||||
if (thisFactory.length == 2) {
|
||||
String factoryPrefix = thisFactory[0].trim();
|
||||
String factoryName = thisFactory[1].trim();
|
||||
ActionProxyFactory obj = container.getInstance(ActionProxyFactory.class, factoryName);
|
||||
if (obj != null) {
|
||||
actionProxyFactories.put(factoryPrefix, obj);
|
||||
} else {
|
||||
LOG.warn("Invalid PrefixBasedActionProxyFactory config entry: [{}]", factory);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -106,8 +109,7 @@ public class PrefixBasedActionProxyFactory extends DefaultActionProxyFactory {
|
||||
LOG.debug("No ActionProxyFactory defined for [{}]", key);
|
||||
}
|
||||
}
|
||||
LOG.debug("Cannot find any matching ActionProxyFactory, falling back to [{}]", defaultFactory);
|
||||
return defaultFactory.createActionProxy(namespace, actionName, methodName, extraContext, executeResult, cleanupContext);
|
||||
LOG.debug("Cannot find any matching ActionProxyFactory, falling back to [{}]", super.getClass().getName());
|
||||
return super.createActionProxy(namespace, actionName, methodName, extraContext, executeResult, cleanupContext);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,10 +31,11 @@ public class BackgroundProcess implements Serializable {
|
||||
|
||||
private static final long serialVersionUID = 3884464776311686443L;
|
||||
|
||||
protected Object action;
|
||||
protected ActionInvocation invocation;
|
||||
//WW-4900 transient since 2.5.15
|
||||
transient protected ActionInvocation invocation;
|
||||
transient protected Exception exception;
|
||||
|
||||
protected String result;
|
||||
protected Exception exception;
|
||||
protected boolean done;
|
||||
|
||||
/**
|
||||
@@ -46,7 +47,6 @@ public class BackgroundProcess implements Serializable {
|
||||
*/
|
||||
public BackgroundProcess(String threadName, final ActionInvocation invocation, int threadPriority) {
|
||||
this.invocation = invocation;
|
||||
this.action = invocation.getAction();
|
||||
try {
|
||||
final Thread t = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
@@ -96,7 +96,7 @@ public class BackgroundProcess implements Serializable {
|
||||
* @return the action.
|
||||
*/
|
||||
public Object getAction() {
|
||||
return action;
|
||||
return invocation.getAction();
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -26,7 +26,9 @@ import org.apache.struts2.dispatcher.Parameter;
|
||||
import org.apache.struts2.dispatcher.HttpParameters;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: description -->
|
||||
@@ -60,14 +62,16 @@ public class CheckboxInterceptor extends AbstractInterceptor {
|
||||
HttpParameters parameters = ai.getInvocationContext().getParameters();
|
||||
Map<String, Parameter> extraParams = new HashMap<>();
|
||||
|
||||
for (String name : parameters.keySet()) {
|
||||
Set<String> checkboxParameters = new HashSet<>();
|
||||
for (Map.Entry<String, Parameter> parameter : parameters.entrySet()) {
|
||||
String name = parameter.getKey();
|
||||
if (name.startsWith("__checkbox_")) {
|
||||
String checkboxName = name.substring("__checkbox_".length());
|
||||
|
||||
Parameter value = parameters.get(name);
|
||||
parameters = parameters.remove(name);
|
||||
Parameter value = parameter.getValue();
|
||||
checkboxParameters.add(name);
|
||||
if (value.isMultiple()) {
|
||||
LOG.debug("Bypassing automatic checkbox detection due to multiple checkboxes of the same name: {}", name);
|
||||
LOG.debug("Bypassing automatic checkbox detection due to multiple checkboxes of the same name: {}", name);
|
||||
continue;
|
||||
}
|
||||
|
||||
@@ -78,7 +82,7 @@ public class CheckboxInterceptor extends AbstractInterceptor {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
parameters.remove(checkboxParameters);
|
||||
|
||||
ai.getInvocationContext().getParameters().appendAll(extraParams);
|
||||
|
||||
|
||||
@@ -243,6 +243,12 @@ public class ExecuteAndWaitInterceptor extends MethodFilterInterceptor {
|
||||
synchronized (httpSession) {
|
||||
BackgroundProcess bp = (BackgroundProcess) session.get(KEY + name);
|
||||
|
||||
//WW-4900 Checks if from a de-serialized session? so background thread missed, let's start a new one.
|
||||
if (bp != null && bp.getInvocation() == null) {
|
||||
session.remove(KEY + name);
|
||||
bp = null;
|
||||
}
|
||||
|
||||
if ((!executeAfterValidationPass || secondTime) && bp == null) {
|
||||
bp = getNewBackgroundProcess(name, actionInvocation, threadPriority);
|
||||
session.put(KEY + name, bp);
|
||||
|
||||
@@ -281,15 +281,17 @@ public class I18nInterceptor extends AbstractInterceptor {
|
||||
|
||||
@Override
|
||||
public Locale store(ActionInvocation invocation, Locale locale) {
|
||||
//save it in session
|
||||
Map<String, Object> session = invocation.getInvocationContext().getSession();
|
||||
HttpSession session = ServletActionContext.getRequest().getSession(false);
|
||||
|
||||
if (session != null) {
|
||||
String sessionId = ServletActionContext.getRequest().getSession().getId();
|
||||
String sessionId = session.getId();
|
||||
synchronized (sessionId.intern()) {
|
||||
session.put(attributeName, locale);
|
||||
invocation.getInvocationContext().getSession().put(attributeName, locale);
|
||||
}
|
||||
} else {
|
||||
LOG.debug("session creation avoided as it doesn't exist already");
|
||||
}
|
||||
|
||||
return locale;
|
||||
}
|
||||
|
||||
@@ -298,19 +300,15 @@ public class I18nInterceptor extends AbstractInterceptor {
|
||||
Locale locale = null;
|
||||
|
||||
LOG.debug("Checks session for saved locale");
|
||||
Map<String, Object> session = invocation.getInvocationContext().getSession();
|
||||
HttpSession session = ServletActionContext.getRequest().getSession(false);
|
||||
|
||||
if (session != null) {
|
||||
//[WW-4741] Do not force session creation while this is a read operation
|
||||
HttpSession httpSession = ServletActionContext.getRequest().getSession(false);
|
||||
if(null != httpSession) {
|
||||
String sessionId = httpSession.getId();
|
||||
synchronized (sessionId.intern()) {
|
||||
Object sessionLocale = session.get(attributeName);
|
||||
if (sessionLocale != null && sessionLocale instanceof Locale) {
|
||||
locale = (Locale) sessionLocale;
|
||||
LOG.debug("Applied session locale: {}", locale);
|
||||
}
|
||||
String sessionId = session.getId();
|
||||
synchronized (sessionId.intern()) {
|
||||
Object sessionLocale = invocation.getInvocationContext().getSession().get(attributeName);
|
||||
if (sessionLocale != null && sessionLocale instanceof Locale) {
|
||||
locale = (Locale) sessionLocale;
|
||||
LOG.debug("Applied session locale: {}", locale);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -215,8 +215,9 @@ public class PostbackResult extends StrutsResultSupport {
|
||||
|
||||
private void writeFormElements(HttpServletRequest request, PrintWriter pw) throws UnsupportedEncodingException {
|
||||
Map<String, String[]> params = request.getParameterMap();
|
||||
for (String name : params.keySet()) {
|
||||
String[] values = params.get(name);
|
||||
for (Map.Entry<String, String[]> entry : params.entrySet()) {
|
||||
String name = entry.getKey();
|
||||
String[] values = entry.getValue();
|
||||
if (isElementIncluded(name, values)) {
|
||||
writeFormElement(pw, name, values);
|
||||
}
|
||||
|
||||
@@ -137,8 +137,8 @@ public class ServletDispatcherResult extends StrutsResultSupport {
|
||||
|
||||
//add parameters passed on the location to #parameters
|
||||
// see WW-2120
|
||||
if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf("?") > 0) {
|
||||
String queryString = finalLocation.substring(finalLocation.indexOf("?") + 1);
|
||||
if (StringUtils.isNotEmpty(finalLocation) && finalLocation.indexOf('?') > 0) {
|
||||
String queryString = finalLocation.substring(finalLocation.indexOf('?') + 1);
|
||||
HttpParameters parameters = getParameters(invocation);
|
||||
Map<String, Object> queryParams = urlHelper.parseQueryString(queryString, true);
|
||||
if (queryParams != null && !queryParams.isEmpty()) {
|
||||
|
||||
@@ -271,7 +271,7 @@ public class ServletRedirectResult extends StrutsResultSupport implements Reflec
|
||||
try {
|
||||
String rawUrl = url;
|
||||
if (url.contains("?")) {
|
||||
rawUrl = url.substring(0, url.indexOf("?"));
|
||||
rawUrl = url.substring(0, url.indexOf('?'));
|
||||
}
|
||||
URI uri = URI.create(rawUrl.replaceAll(" ", "%20"));
|
||||
if (uri.isAbsolute()) {
|
||||
|
||||
@@ -20,7 +20,6 @@ package org.apache.struts2.util;
|
||||
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
|
||||
import java.io.Serializable;
|
||||
import java.util.HashMap;
|
||||
@@ -56,10 +55,14 @@ public class InvocationSessionStore {
|
||||
return null;
|
||||
}
|
||||
|
||||
ValueStack stack = invocationContext.invocation.getStack();
|
||||
ActionContext.getContext().setValueStack(stack);
|
||||
ActionInvocation savedInvocation = null;
|
||||
if (invocationContext.invocation != null) {
|
||||
savedInvocation = invocationContext.invocation;
|
||||
ActionContext.setContext(savedInvocation.getInvocationContext());
|
||||
ActionContext.getContext().setValueStack(savedInvocation.getStack());
|
||||
}
|
||||
|
||||
return invocationContext.invocation.deserialize(ActionContext.getContext());
|
||||
return savedInvocation;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -71,7 +74,7 @@ public class InvocationSessionStore {
|
||||
* @param invocation the action invocation
|
||||
*/
|
||||
public static void storeInvocation(String key, String token, ActionInvocation invocation) {
|
||||
InvocationContext invocationContext = new InvocationContext(invocation.serialize(), token);
|
||||
InvocationContext invocationContext = new InvocationContext(invocation, token);
|
||||
Map invocationMap = getInvocationMap();
|
||||
invocationMap.put(key, invocationContext);
|
||||
setInvocationMap(invocationMap);
|
||||
@@ -109,7 +112,9 @@ public class InvocationSessionStore {
|
||||
|
||||
private static final long serialVersionUID = -286697666275777888L;
|
||||
|
||||
ActionInvocation invocation;
|
||||
//WW-4873 transient since 2.5.15
|
||||
transient ActionInvocation invocation;
|
||||
|
||||
String token;
|
||||
|
||||
public InvocationContext(ActionInvocation invocation, String token) {
|
||||
|
||||
@@ -524,8 +524,8 @@ public class FreemarkerManager {
|
||||
ScopesHashModel model = buildScopesHashModel(servletContext, request, response, wrapper, stack);
|
||||
populateContext(model, stack, action, request, response);
|
||||
if (tagLibraries != null) {
|
||||
for (String prefix : tagLibraries.keySet()) {
|
||||
model.put(prefix, tagLibraries.get(prefix).getModels(stack, request, response));
|
||||
for (Map.Entry<String, TagLibraryModelProvider> entry : tagLibraries.entrySet()) {
|
||||
model.put(entry.getKey(), entry.getValue().getModels(stack, request, response));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -98,7 +98,7 @@ public class TagUtils {
|
||||
// last part (/foo/bar/baz.xyz -> /foo/bar)
|
||||
|
||||
String path = RequestUtils.getServletPath(request);
|
||||
return path.substring(0, path.lastIndexOf("/"));
|
||||
return path.substring(0, path.lastIndexOf('/'));
|
||||
}
|
||||
} else {
|
||||
return invocation.getProxy().getNamespace();
|
||||
|
||||
+1
-1
@@ -146,7 +146,7 @@ public abstract class AbstractDirective extends Directive {
|
||||
// node.value uses the StrutsValueStack to evaluate the directive's value parameter
|
||||
String param = node.value(contextAdapter).toString();
|
||||
|
||||
int idx = param.indexOf("=");
|
||||
int idx = param.indexOf('=');
|
||||
|
||||
if (idx != -1) {
|
||||
String property = param.substring(0, idx);
|
||||
|
||||
@@ -12,7 +12,7 @@ Please do not edit it directly.
|
||||
<h2>Description</h2>
|
||||
<p>
|
||||
<!-- START SNIPPET: tagdescription -->
|
||||
Prints debugging information
|
||||
Prints debugging information (Only if 'struts.devMode' is enabled)
|
||||
<!-- END SNIPPET: tagdescription -->
|
||||
</p>
|
||||
|
||||
|
||||
@@ -18,6 +18,9 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2;
|
||||
|
||||
import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
|
||||
import com.opensymphony.xwork2.conversion.impl.FooBarConverter;
|
||||
import com.opensymphony.xwork2.util.Bar;
|
||||
import com.opensymphony.xwork2.validator.annotations.IntRangeFieldValidator;
|
||||
import com.opensymphony.xwork2.validator.annotations.RequiredStringValidator;
|
||||
import com.opensymphony.xwork2.validator.annotations.Validations;
|
||||
@@ -37,6 +40,7 @@ public class AnnotatedTestBean {
|
||||
private Date birth;
|
||||
private String name;
|
||||
private int count;
|
||||
private Bar bar;
|
||||
|
||||
//~ Constructors ///////////////////////////////////////////////////////////
|
||||
|
||||
@@ -76,4 +80,13 @@ public class AnnotatedTestBean {
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Bar getSupperBarObj() {
|
||||
return bar;
|
||||
}
|
||||
|
||||
@TypeConversion(converter = "com.opensymphony.xwork2.conversion.impl.FooBarConverter")
|
||||
public void setSupperBarObj(Bar b) {
|
||||
bar = b;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,8 @@ import com.opensymphony.xwork2.config.entities.InterceptorMapping;
|
||||
import com.opensymphony.xwork2.config.entities.ResultConfig;
|
||||
import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
|
||||
import com.opensymphony.xwork2.mock.MockActionProxy;
|
||||
import com.opensymphony.xwork2.mock.MockContainer;
|
||||
import com.opensymphony.xwork2.mock.MockInterceptor;
|
||||
import com.opensymphony.xwork2.mock.MockLazyInterceptor;
|
||||
import com.opensymphony.xwork2.mock.MockResult;
|
||||
import com.opensymphony.xwork2.ognl.OgnlUtil;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import com.opensymphony.xwork2.util.ValueStackFactory;
|
||||
@@ -34,7 +33,6 @@ import org.apache.struts2.dispatcher.HttpParameters;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
|
||||
/**
|
||||
@@ -69,38 +67,22 @@ public class DefaultActionInvocationTest extends XWorkTestCase {
|
||||
container.inject(defaultActionInvocation);
|
||||
defaultActionInvocation.stack = container.getInstance(ValueStackFactory.class).createValueStack();
|
||||
|
||||
defaultActionInvocation.setResultCode("");//is possible when result is not executed already
|
||||
defaultActionInvocation.invoke();
|
||||
assertTrue(mockInterceptor1.isExecuted());
|
||||
assertTrue(mockInterceptor2.isExecuted());
|
||||
assertTrue(mockInterceptor3.isExecuted());
|
||||
}
|
||||
|
||||
public void testSerialization() throws Exception {
|
||||
// given
|
||||
DefaultActionInvocation actionInvocation = new DefaultActionInvocation(new HashMap<String, Object>(), false);
|
||||
actionInvocation.setContainer(new MockContainer());
|
||||
|
||||
// when
|
||||
DefaultActionInvocation serializable = (DefaultActionInvocation) actionInvocation.serialize();
|
||||
|
||||
// then
|
||||
assertNull(actionInvocation.container);
|
||||
assertNull(serializable.container);
|
||||
}
|
||||
|
||||
public void testDeserialization() throws Exception {
|
||||
// given
|
||||
DefaultActionInvocation actionInvocation = new DefaultActionInvocation(new HashMap<String, Object>(), false);
|
||||
MockContainer mockContainer = new MockContainer();
|
||||
ActionContext.getContext().setContainer(mockContainer);
|
||||
|
||||
// when
|
||||
DefaultActionInvocation deserializable = (DefaultActionInvocation) actionInvocation.deserialize(ActionContext.getContext());
|
||||
|
||||
// then
|
||||
assertNotNull(actionInvocation.container);
|
||||
assertNotNull(deserializable.container);
|
||||
assertEquals(mockContainer, deserializable.container);
|
||||
assertTrue(defaultActionInvocation.isExecuted());
|
||||
try {
|
||||
defaultActionInvocation.setResultCode("");
|
||||
fail("should not possible when result already executed");
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
try {
|
||||
defaultActionInvocation.invoke();
|
||||
fail("should not possible when result already executed");
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testInvokingExistingExecuteMethod() throws Exception {
|
||||
@@ -340,6 +322,74 @@ public class DefaultActionInvocationTest extends XWorkTestCase {
|
||||
assertEquals("this is blah", action.getName());
|
||||
}
|
||||
|
||||
public void testActionEventListener() throws Exception {
|
||||
ActionProxy actionProxy = actionProxyFactory.createActionProxy("",
|
||||
"ExceptionFoo", "exceptionMethod", new HashMap<String, Object>());
|
||||
DefaultActionInvocation defaultActionInvocation = (DefaultActionInvocation) actionProxy.getInvocation();
|
||||
|
||||
SimpleActionEventListener actionEventListener = new SimpleActionEventListener("prepared", "exceptionHandled");
|
||||
defaultActionInvocation.setActionEventListener(actionEventListener);
|
||||
defaultActionInvocation.init(actionProxy);
|
||||
|
||||
SimpleAction action = (SimpleAction) defaultActionInvocation.getAction();
|
||||
action.setThrowException(true);
|
||||
|
||||
defaultActionInvocation.unknownHandlerManager = new DefaultUnknownHandlerManager() {
|
||||
@Override
|
||||
public boolean hasUnknownHandlers() {
|
||||
return false;
|
||||
}
|
||||
};
|
||||
|
||||
String result = defaultActionInvocation.invoke();
|
||||
|
||||
// then
|
||||
assertEquals("prepared", action.getName());
|
||||
assertEquals("exceptionHandled", result);
|
||||
}
|
||||
|
||||
public void testActionChainResult() throws Exception {
|
||||
ActionProxy actionProxy = actionProxyFactory.createActionProxy("", "Foo", null,
|
||||
new HashMap<String, Object>());
|
||||
DefaultActionInvocation defaultActionInvocation = (DefaultActionInvocation) actionProxy.getInvocation();
|
||||
defaultActionInvocation.init(actionProxy);
|
||||
|
||||
SimpleAction action = (SimpleAction) defaultActionInvocation.getAction();
|
||||
action.setFoo(1);
|
||||
action.setBar(2);
|
||||
|
||||
defaultActionInvocation.invoke();
|
||||
|
||||
// then
|
||||
assertTrue(defaultActionInvocation.result instanceof ActionChainResult);
|
||||
Result result = defaultActionInvocation.getResult();
|
||||
assertTrue(result instanceof MockResult);
|
||||
}
|
||||
|
||||
public void testNoResultDefined() throws Exception {
|
||||
ActionProxy actionProxy = actionProxyFactory.createActionProxy("", "Foo", null,
|
||||
new HashMap<String, Object>());
|
||||
DefaultActionInvocation defaultActionInvocation = (DefaultActionInvocation) actionProxy.getInvocation();
|
||||
defaultActionInvocation.init(actionProxy);
|
||||
|
||||
try {
|
||||
defaultActionInvocation.invoke();//foo==bar so returns error which is not defined
|
||||
fail("should not possible when result is not defined");
|
||||
} catch (Exception ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public void testNullResultPossible() throws Exception {
|
||||
ActionProxy actionProxy = actionProxyFactory.createActionProxy("",
|
||||
"NullFoo", "nullMethod", new HashMap<String, Object>());
|
||||
DefaultActionInvocation defaultActionInvocation = (DefaultActionInvocation) actionProxy.getInvocation();
|
||||
defaultActionInvocation.init(actionProxy);
|
||||
|
||||
String result = defaultActionInvocation.invoke();
|
||||
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
@@ -350,6 +400,29 @@ public class DefaultActionInvocationTest extends XWorkTestCase {
|
||||
loadConfigurationProviders(configurationProvider);
|
||||
}
|
||||
|
||||
|
||||
private class SimpleActionEventListener implements ActionEventListener {
|
||||
|
||||
private String name;
|
||||
private String result;
|
||||
|
||||
SimpleActionEventListener(String name, String result) {
|
||||
|
||||
this.name = name;
|
||||
this.result = result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object prepare(Object action, ValueStack stack) {
|
||||
((SimpleAction)action).setName(name);
|
||||
return action;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String handleException(Throwable t, ValueStack stack) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class DefaultActionInvocationTester extends DefaultActionInvocation {
|
||||
|
||||
@@ -0,0 +1,83 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2;
|
||||
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.config.providers.SomeUnknownHandler;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* Partial test to the DefaultUnknownHandlerManager to understand the relationship between Manager and Handlers.
|
||||
*
|
||||
*/
|
||||
public class DefaultUnknownHandlerManagerTest extends TestCase {
|
||||
|
||||
ActionConfig actionConfig;
|
||||
SomeUnknownHandler someUnknownHandler;
|
||||
|
||||
/**
|
||||
* Relationshsip when UnknownAction method is called.
|
||||
*
|
||||
*/
|
||||
public void testHandleUnknownAction() {
|
||||
|
||||
DefaultUnknownHandlerManager defaultUnknownHandlerManager = new DefaultUnknownHandlerManager();
|
||||
defaultUnknownHandlerManager.unknownHandlers = new ArrayList<>();
|
||||
defaultUnknownHandlerManager.unknownHandlers.add(someUnknownHandler);
|
||||
|
||||
ActionConfig newActionConfig = defaultUnknownHandlerManager.handleUnknownAction("arbitraryNameSpace", "arbitraryActionName");
|
||||
|
||||
assertEquals(newActionConfig, actionConfig);
|
||||
}
|
||||
|
||||
/**
|
||||
* Relationship when UnknownActionMethod method called.
|
||||
*
|
||||
*/
|
||||
public void testHandelUnknownActionMethod() throws Exception {
|
||||
DefaultUnknownHandlerManager defaultUnknownHandlerManager = new DefaultUnknownHandlerManager();
|
||||
defaultUnknownHandlerManager.unknownHandlers = new ArrayList<>();
|
||||
defaultUnknownHandlerManager.unknownHandlers.add(someUnknownHandler);
|
||||
|
||||
String result = null;
|
||||
|
||||
for (int i = 0; i < 10 ; i++) {
|
||||
result = (String) defaultUnknownHandlerManager.handleUnknownMethod(this, "someMethodName");
|
||||
assertEquals(result, "specialActionMethod");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
// Make sure we are using the actionConfig we initialized.
|
||||
ActionConfig.Builder actionConfigBuilder = new ActionConfig.Builder( "com", "someAction", "someClass");
|
||||
actionConfig = actionConfigBuilder.build();
|
||||
someUnknownHandler = new SomeUnknownHandler();
|
||||
|
||||
someUnknownHandler.setActionConfig(actionConfig);
|
||||
someUnknownHandler.setActionMethodResult("specialActionMethod");
|
||||
}
|
||||
|
||||
}
|
||||
@@ -229,6 +229,10 @@ public class SimpleAction extends ActionSupport {
|
||||
return "OK";
|
||||
}
|
||||
|
||||
public String nullMethod() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String execute() throws Exception {
|
||||
if (foo == bar) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import com.mockobjects.dynamic.Mock;
|
||||
import com.opensymphony.xwork2.FileManagerFactory;
|
||||
import com.opensymphony.xwork2.XWorkTestCase;
|
||||
import com.opensymphony.xwork2.config.providers.XWorkConfigurationProvider;
|
||||
import com.opensymphony.xwork2.conversion.TypeConverterHolder;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.inject.ContainerBuilder;
|
||||
import com.opensymphony.xwork2.util.location.LocatableProperties;
|
||||
@@ -152,6 +153,12 @@ public class ConfigurationManagerTest extends XWorkTestCase {
|
||||
configProviderMock.verify();
|
||||
}
|
||||
|
||||
public void testEarlyInitializable() throws Exception {
|
||||
TypeConverterHolder converterHolder = container.getInstance(TypeConverterHolder.class);
|
||||
assertTrue("java.io.File mapping should being putted by DefaultConversionPropertiesProcessor.init()",
|
||||
converterHolder.containsDefaultMapping("java.io.File"));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
super.setUp();
|
||||
|
||||
+9
-1
@@ -177,7 +177,7 @@ public class AnnotationXWorkConverterTest extends XWorkTestCase {
|
||||
assertEquals("Invalid field value for field \"foo\".", message);
|
||||
}
|
||||
|
||||
public void testFindConversionMappingForInterface() {
|
||||
public void testFindConversionMappingForInterfaceAndSuperclass() {
|
||||
ModelDrivenAnnotationAction2 action = new ModelDrivenAnnotationAction2();
|
||||
ValueStack stack = ActionContext.getContext().getValueStack();
|
||||
stack.push(action);
|
||||
@@ -193,6 +193,14 @@ public class AnnotationXWorkConverterTest extends XWorkTestCase {
|
||||
|
||||
Bar b = (Bar) o;
|
||||
assertEquals(value, b.getTitle() + ":" + b.getSomethingElse());
|
||||
|
||||
String value2 = "qwer:456";
|
||||
Object o2 = converter.convertValue(ognlStackContext, action.getModel(), null, "supperBarObj", value2, Bar.class);
|
||||
assertNotNull(o2);
|
||||
assertTrue("class is: " + o.getClass(), o2 instanceof Bar);
|
||||
|
||||
Bar b2 = (Bar) o2;
|
||||
assertEquals(value2, b2.getTitle() + ":" + b2.getSomethingElse());
|
||||
}
|
||||
|
||||
public void testLocalizedDateConversion() throws Exception {
|
||||
|
||||
@@ -20,6 +20,9 @@ package com.opensymphony.xwork2.inject;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import java.security.Permission;
|
||||
import java.util.concurrent.Callable;
|
||||
|
||||
/**
|
||||
* ContainerImpl Tester.
|
||||
*
|
||||
@@ -33,11 +36,25 @@ public class ContainerImplTest extends TestCase {
|
||||
|
||||
@Override
|
||||
protected void setUp() throws Exception {
|
||||
System.setSecurityManager(null);
|
||||
|
||||
super.setUp();
|
||||
ContainerBuilder cb = new ContainerBuilder();
|
||||
cb.constant("methodCheck.name", "Lukasz");
|
||||
cb.constant("fieldCheck.name", "Lukasz");
|
||||
cb.factory(EarlyInitializable.class, EarlyInitializableBean.class, Scope.SINGLETON);
|
||||
cb.factory(Initializable.class, InitializableBean.class, Scope.SINGLETON);
|
||||
cb.factory(EarlyInitializable.class, "prototypeEarlyInitializable", EarlyInitializableBean.class, Scope.PROTOTYPE);
|
||||
cb.factory(Initializable.class, "prototypeInitializable", InitializableBean.class, Scope.PROTOTYPE);
|
||||
cb.factory(Initializable.class, "requestInitializable", InitializableBean.class, Scope.REQUEST);
|
||||
cb.factory(Initializable.class, "sessionInitializable", InitializableBean.class, Scope.SESSION);
|
||||
cb.factory(Initializable.class, "threadInitializable", InitializableBean.class, Scope.THREAD);
|
||||
cb.factory(Initializable.class, "wizardInitializable", InitializableBean.class, Scope.WIZARD);
|
||||
c = cb.create(false);
|
||||
c.setScopeStrategy(new TestScopeStrategy());
|
||||
|
||||
Class.forName(FieldCheck.class.getName());
|
||||
Class.forName(ContainerImpl.FieldInjector.class.getName());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,17 +93,15 @@ public class ContainerImplTest extends TestCase {
|
||||
* Inject values into field under SecurityManager
|
||||
*/
|
||||
public void testFieldInjectorWithSecurityEnabled() throws Exception {
|
||||
|
||||
System.setSecurityManager(new SecurityManager());
|
||||
System.setSecurityManager(new TestSecurityManager());
|
||||
|
||||
FieldCheck fieldCheck = new FieldCheck();
|
||||
|
||||
try {
|
||||
c.inject(fieldCheck);
|
||||
assertEquals(fieldCheck.getName(), "Lukasz");
|
||||
fail("Exception should be thrown!");
|
||||
} catch (DependencyException expected) {
|
||||
// that was expected
|
||||
} catch (Error | DependencyException expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -94,22 +109,97 @@ public class ContainerImplTest extends TestCase {
|
||||
* Inject values into method under SecurityManager
|
||||
*/
|
||||
public void testMethodInjectorWithSecurityEnabled() throws Exception {
|
||||
|
||||
// not needed, already set
|
||||
//System.setSecurityManager(new SecurityManager());
|
||||
System.setSecurityManager(new TestSecurityManager());
|
||||
|
||||
MethodCheck methodCheck = new MethodCheck();
|
||||
|
||||
try {
|
||||
c.inject(methodCheck);
|
||||
assertEquals(methodCheck.getName(), "Lukasz");
|
||||
fail("Exception sould be thrown!");
|
||||
} catch (DependencyException expected) {
|
||||
// that was expected
|
||||
fail("Exception should be thrown!");
|
||||
} catch (DependencyException | Error expected) {
|
||||
assertTrue(true);
|
||||
}
|
||||
}
|
||||
|
||||
class FieldCheck {
|
||||
public void testEarlyInitializable() throws Exception {
|
||||
assertTrue("should being initialized already", EarlyInitializableBean.initializedEarly);
|
||||
|
||||
EarlyInitializableCheck earlyInitializableCheck = new EarlyInitializableCheck();
|
||||
c.inject(earlyInitializableCheck);
|
||||
assertEquals("initialized early", ((EarlyInitializableBean) earlyInitializableCheck.getEarlyInitializable()).getMessage());
|
||||
assertEquals("initialized early", ((EarlyInitializableBean) earlyInitializableCheck.getPrototypeEarlyInitializable()).getMessage());
|
||||
|
||||
EarlyInitializableCheck earlyInitializableCheck2 = new EarlyInitializableCheck();
|
||||
c.inject(earlyInitializableCheck2);
|
||||
assertEquals("singletons should not being initialized twice", "initialized early",
|
||||
((EarlyInitializableBean) earlyInitializableCheck2.getEarlyInitializable()).getMessage());
|
||||
assertEquals("initialized early", ((EarlyInitializableBean) earlyInitializableCheck2.getPrototypeEarlyInitializable()).getMessage());
|
||||
|
||||
assertEquals("singletons should being instantiated once",
|
||||
earlyInitializableCheck.getEarlyInitializable(), earlyInitializableCheck2.getEarlyInitializable());
|
||||
assertNotSame("prototypes should being instantiated for each injection",
|
||||
earlyInitializableCheck.getPrototypeEarlyInitializable(), earlyInitializableCheck2.getPrototypeEarlyInitializable());
|
||||
}
|
||||
|
||||
public void testInitializable() throws Exception {
|
||||
assertFalse("should not being initialized already", InitializableBean.initialized);
|
||||
|
||||
InitializableCheck initializableCheck = new InitializableCheck();
|
||||
c.inject(initializableCheck);
|
||||
assertTrue("should being initialized here", InitializableBean.initialized);
|
||||
assertEquals("initialized", ((InitializableBean) initializableCheck.getInitializable()).getMessage());
|
||||
assertEquals("initialized", ((InitializableBean) initializableCheck.getPrototypeInitializable()).getMessage());
|
||||
|
||||
InitializableCheck initializableCheck2 = new InitializableCheck();
|
||||
c.inject(initializableCheck2);
|
||||
assertEquals("singletons should not being initialized twice", "initialized",
|
||||
((InitializableBean) initializableCheck2.getInitializable()).getMessage());
|
||||
assertEquals("initialized", ((InitializableBean) initializableCheck2.getPrototypeInitializable()).getMessage());
|
||||
assertEquals("threads should not being initialized twice", "initialized",
|
||||
((InitializableBean) initializableCheck2.getThreadInitializable()).getMessage());
|
||||
|
||||
assertEquals("singletons should being instantiated once",
|
||||
initializableCheck.getInitializable(), initializableCheck2.getInitializable());
|
||||
assertNotSame("prototypes should being instantiated for each injection",
|
||||
initializableCheck.getPrototypeInitializable(), initializableCheck2.getPrototypeInitializable());
|
||||
assertEquals("threads should being instantiated once for each thread",
|
||||
initializableCheck.getThreadInitializable(), initializableCheck2.getThreadInitializable());
|
||||
|
||||
final InitializableCheck initializableCheck3 = new InitializableCheck();
|
||||
final TestScopeStrategy testScopeStrategy = new TestScopeStrategy();
|
||||
Thread thread = new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
ContainerBuilder cb2 = new ContainerBuilder();
|
||||
cb2.factory(EarlyInitializable.class, EarlyInitializableBean.class, Scope.SINGLETON);
|
||||
cb2.factory(Initializable.class, InitializableBean.class, Scope.SINGLETON);
|
||||
cb2.factory(EarlyInitializable.class, "prototypeEarlyInitializable", EarlyInitializableBean.class, Scope.PROTOTYPE);
|
||||
cb2.factory(Initializable.class, "prototypeInitializable", InitializableBean.class, Scope.PROTOTYPE);
|
||||
cb2.factory(Initializable.class, "requestInitializable", InitializableBean.class, Scope.REQUEST);
|
||||
cb2.factory(Initializable.class, "sessionInitializable", InitializableBean.class, Scope.SESSION);
|
||||
cb2.factory(Initializable.class, "threadInitializable", InitializableBean.class, Scope.THREAD);
|
||||
cb2.factory(Initializable.class, "wizardInitializable", InitializableBean.class, Scope.WIZARD);
|
||||
Container c2 = cb2.create(false);
|
||||
c2.setScopeStrategy(testScopeStrategy);
|
||||
c2.inject(initializableCheck3);
|
||||
}
|
||||
});
|
||||
thread.run();
|
||||
thread.join();
|
||||
assertNotSame("threads should being instantiated in new threads",
|
||||
initializableCheck.getThreadInitializable(), initializableCheck3.getThreadInitializable());
|
||||
assertEquals("initialized", ((InitializableBean) initializableCheck3.getThreadInitializable()).getMessage());
|
||||
|
||||
assertEquals("initialized", ((InitializableBean) initializableCheck3.getRequestInitializable()).getMessage());
|
||||
assertEquals("initialized", ((InitializableBean) initializableCheck3.getSessionInitializable()).getMessage());
|
||||
assertEquals("initialized", ((InitializableBean) initializableCheck3.getWizardInitializable()).getMessage());
|
||||
|
||||
assertEquals(testScopeStrategy.requestInitializable, initializableCheck3.getRequestInitializable());
|
||||
assertEquals(testScopeStrategy.sessionInitializable, initializableCheck3.getSessionInitializable());
|
||||
assertEquals(testScopeStrategy.wizardInitializable, initializableCheck3.getWizardInitializable());
|
||||
}
|
||||
|
||||
public static class FieldCheck {
|
||||
|
||||
@Inject("fieldCheck.name")
|
||||
private String name;
|
||||
@@ -119,7 +209,7 @@ public class ContainerImplTest extends TestCase {
|
||||
}
|
||||
}
|
||||
|
||||
class MethodCheck {
|
||||
public static class MethodCheck {
|
||||
|
||||
private String name;
|
||||
|
||||
@@ -134,4 +224,131 @@ public class ContainerImplTest extends TestCase {
|
||||
|
||||
}
|
||||
|
||||
class InitializableCheck {
|
||||
|
||||
private Initializable initializable;
|
||||
private Initializable prototypeInitializable;
|
||||
private Initializable requestInitializable;
|
||||
private Initializable sessionInitializable;
|
||||
private Initializable threadInitializable;
|
||||
private Initializable wizardInitializable;
|
||||
|
||||
@Inject
|
||||
public void setInitializable(Initializable initializable) {
|
||||
this.initializable = initializable;
|
||||
}
|
||||
|
||||
@Inject("prototypeInitializable")
|
||||
public void setPrototypeInitializable(Initializable prototypeInitializable) {
|
||||
this.prototypeInitializable = prototypeInitializable;
|
||||
}
|
||||
|
||||
@Inject("requestInitializable")
|
||||
public void setRequestInitializable(Initializable requestInitializable) {
|
||||
this.requestInitializable = requestInitializable;
|
||||
}
|
||||
|
||||
@Inject("sessionInitializable")
|
||||
public void setSessionInitializable(Initializable sessionInitializable) {
|
||||
this.sessionInitializable = sessionInitializable;
|
||||
}
|
||||
|
||||
@Inject("threadInitializable")
|
||||
public void setThreadInitializable(Initializable threadInitializable) {
|
||||
this.threadInitializable = threadInitializable;
|
||||
}
|
||||
|
||||
@Inject("wizardInitializable")
|
||||
public void setWizardInitializable(Initializable wizardInitializable) {
|
||||
this.wizardInitializable = wizardInitializable;
|
||||
}
|
||||
|
||||
public Initializable getRequestInitializable() {
|
||||
return requestInitializable;
|
||||
}
|
||||
|
||||
public Initializable getSessionInitializable() {
|
||||
return sessionInitializable;
|
||||
}
|
||||
|
||||
public Initializable getThreadInitializable() {
|
||||
return threadInitializable;
|
||||
}
|
||||
|
||||
public Initializable getWizardInitializable() {
|
||||
return wizardInitializable;
|
||||
}
|
||||
|
||||
public Initializable getInitializable() {
|
||||
return initializable;
|
||||
}
|
||||
|
||||
public Initializable getPrototypeInitializable() {
|
||||
return prototypeInitializable;
|
||||
}
|
||||
}
|
||||
|
||||
class EarlyInitializableCheck {
|
||||
|
||||
private EarlyInitializable earlyInitializable;
|
||||
private EarlyInitializable prototypeEarlyInitializable;
|
||||
|
||||
@Inject
|
||||
public void setEarlyInitializable(EarlyInitializable earlyInitializable) {
|
||||
this.earlyInitializable = earlyInitializable;
|
||||
}
|
||||
|
||||
@Inject("prototypeEarlyInitializable")
|
||||
public void setPrototypeEarlyInitializable(EarlyInitializable prototypeEarlyInitializable) {
|
||||
this.prototypeEarlyInitializable = prototypeEarlyInitializable;
|
||||
}
|
||||
|
||||
public EarlyInitializable getEarlyInitializable() {
|
||||
return earlyInitializable;
|
||||
}
|
||||
|
||||
public EarlyInitializable getPrototypeEarlyInitializable() {
|
||||
return prototypeEarlyInitializable;
|
||||
}
|
||||
}
|
||||
|
||||
class TestSecurityManager extends SecurityManager {
|
||||
|
||||
@Override
|
||||
public void checkPermission(Permission perm) {
|
||||
if (!"setSecurityManager".equals(perm.getName())) {
|
||||
super.checkPermission(perm);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class TestScopeStrategy implements Scope.Strategy {
|
||||
Initializable requestInitializable;
|
||||
Initializable sessionInitializable;
|
||||
Initializable wizardInitializable;
|
||||
|
||||
@Override
|
||||
public <T> T findInRequest(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
|
||||
if (requestInitializable == null) {
|
||||
requestInitializable = (Initializable) factory.call();
|
||||
}
|
||||
return (T) requestInitializable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T findInSession(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
|
||||
if (sessionInitializable == null) {
|
||||
sessionInitializable = (Initializable) factory.call();
|
||||
}
|
||||
return (T) sessionInitializable;
|
||||
}
|
||||
|
||||
@Override
|
||||
public <T> T findInWizard(Class<T> type, String name, Callable<? extends T> factory) throws Exception {
|
||||
if (wizardInitializable == null) {
|
||||
wizardInitializable = (Initializable) factory.call();
|
||||
}
|
||||
return (T) wizardInitializable;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.inject;
|
||||
|
||||
class EarlyInitializableBean implements EarlyInitializable {
|
||||
private String message = "";
|
||||
static boolean initializedEarly;
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
message += "initialized early";
|
||||
initializedEarly = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.inject;
|
||||
|
||||
public class InitializableBean implements Initializable {
|
||||
private String message = "";
|
||||
static boolean initialized;
|
||||
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
message += "initialized";
|
||||
initialized = true;
|
||||
}
|
||||
}
|
||||
@@ -582,7 +582,7 @@ public class OgnlUtilTest extends XWorkTestCase {
|
||||
// just do some of the 15 tests
|
||||
Map beans = ognlUtil.getBeanMap(foo);
|
||||
assertNotNull(beans);
|
||||
assertEquals(19, beans.size());
|
||||
assertEquals(21, beans.size());
|
||||
assertEquals("Hello Santa", beans.get("title"));
|
||||
assertEquals(new Long("123"), beans.get("ALong"));
|
||||
assertEquals(new Integer("44"), beans.get("number"));
|
||||
|
||||
@@ -733,11 +733,24 @@ public class OgnlValueStackTest extends XWorkTestCase {
|
||||
assertEquals("Cat One", ((Cat) foo.getCats().get(0)).getName());
|
||||
assertEquals("Cat Two", ((Cat) foo.getCats().get(1)).getName());
|
||||
|
||||
vs.setValue("annotatedCats[0].name", "Cat One By Annotation");
|
||||
vs.setValue("annotatedCats[1].name", "Cat Two By Annotation");
|
||||
assertNotNull(foo.getAnnotatedCats());
|
||||
assertEquals(2, foo.getAnnotatedCats().size());
|
||||
assertEquals("Cat One By Annotation", ((Cat) foo.getAnnotatedCats().get(0)).getName());
|
||||
assertEquals("Cat Two By Annotation", ((Cat) foo.getAnnotatedCats().get(1)).getName());
|
||||
|
||||
vs.setValue("cats[0].foo.cats[1].name", "Deep null cat");
|
||||
assertNotNull(((Cat) foo.getCats().get(0)).getFoo());
|
||||
assertNotNull(((Cat) foo.getCats().get(0)).getFoo().getCats());
|
||||
assertNotNull(((Cat) foo.getCats().get(0)).getFoo().getCats().get(1));
|
||||
assertEquals("Deep null cat", ((Cat) ((Cat) foo.getCats().get(0)).getFoo().getCats().get(1)).getName());
|
||||
|
||||
vs.setValue("annotatedCats[0].foo.annotatedCats[1].name", "Deep null cat by annotation");
|
||||
assertNotNull(((Cat) foo.getAnnotatedCats().get(0)).getFoo());
|
||||
assertNotNull(((Cat) foo.getAnnotatedCats().get(0)).getFoo().getAnnotatedCats());
|
||||
assertNotNull(((Cat) foo.getAnnotatedCats().get(0)).getFoo().getAnnotatedCats().get(1));
|
||||
assertEquals("Deep null cat by annotation", ((Cat) ((Cat) foo.getAnnotatedCats().get(0)).getFoo().getAnnotatedCats().get(1)).getName());
|
||||
}
|
||||
|
||||
public void testSetMultiple() {
|
||||
|
||||
@@ -144,7 +144,11 @@ public class SetPropertiesTest extends XWorkTestCase {
|
||||
public Object create(Context context) throws Exception {
|
||||
return new MockObjectTypeDeterminer(null,Cat.class,null,allowAdditions);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return Cat.class;
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -244,6 +248,7 @@ public class SetPropertiesTest extends XWorkTestCase {
|
||||
Bar bar2 = new Bar();
|
||||
bar2.setId(new Long(22));
|
||||
barColl.add(bar2);
|
||||
foo.setAnnotatedBarCollection(barColl);
|
||||
//try modifying bar1 and bar2
|
||||
//check the logs here to make sure
|
||||
//the Map is being created
|
||||
@@ -262,13 +267,31 @@ public class SetPropertiesTest extends XWorkTestCase {
|
||||
assertEquals(bar1Title, next.getTitle());
|
||||
}
|
||||
}
|
||||
Bar bar3 = new Bar();
|
||||
bar3.setId(new Long(33));
|
||||
barColl.add(bar3);
|
||||
Bar bar4 = new Bar();
|
||||
bar4.setId(new Long(44));
|
||||
barColl.add(bar4);
|
||||
String bar1TitleByAnnotation = "The Phantom Menace By Annotation";
|
||||
String bar2TitleByAnnotation = "The Clone Wars By Annotation";
|
||||
vs.setValue("annotatedBarCollection(44).title", bar2TitleByAnnotation);
|
||||
vs.setValue("annotatedBarCollection(33).title", bar1TitleByAnnotation);
|
||||
for (Object aBarColl : barColl) {
|
||||
Bar next = (Bar) aBarColl;
|
||||
if (next.getId().intValue() == 44) {
|
||||
assertEquals(bar2TitleByAnnotation, next.getTitle());
|
||||
} else if (next.getId().intValue() == 33) {
|
||||
assertEquals(bar1TitleByAnnotation, next.getTitle());
|
||||
}
|
||||
}
|
||||
//now test adding to a collection
|
||||
String bar3Title = "Revenge of the Sith";
|
||||
String bar4Title = "A New Hope";
|
||||
vs.setValue("barCollection.makeNew[4].title", bar4Title, true);
|
||||
vs.setValue("barCollection.makeNew[0].title", bar3Title, true);
|
||||
|
||||
assertEquals(4, barColl.size());
|
||||
assertEquals(6, barColl.size());
|
||||
|
||||
for (Object aBarColl : barColl) {
|
||||
Bar next = (Bar) aBarColl;
|
||||
@@ -279,6 +302,24 @@ public class SetPropertiesTest extends XWorkTestCase {
|
||||
}
|
||||
}
|
||||
|
||||
//now test adding to a collection by annotation
|
||||
String bar3TitleByAnnotation = "Revenge of the Sith By Annotation";
|
||||
String bar4TitleByAnnotation = "A New Hope By Annotation";
|
||||
vs.setValue("annotatedBarCollection.makeNew[5].title", bar4TitleByAnnotation, true);
|
||||
vs.setValue("annotatedBarCollection.makeNew[1].title", bar3TitleByAnnotation, true);
|
||||
|
||||
assertEquals(8, barColl.size());
|
||||
|
||||
for (Object aBarColl : barColl) {
|
||||
Bar next = (Bar) aBarColl;
|
||||
if (next.getId() == null) {
|
||||
assertNotNull(next.getTitle());
|
||||
assertTrue(next.getTitle().equals(bar4TitleByAnnotation)
|
||||
|| next.getTitle().equals(bar3TitleByAnnotation)
|
||||
|| next.getTitle().equals(bar4Title)
|
||||
|| next.getTitle().equals(bar3Title));
|
||||
}
|
||||
}
|
||||
}
|
||||
public void testAddingToCollectionBasedOnPermission() {
|
||||
final MockObjectTypeDeterminer determiner = new MockObjectTypeDeterminer(Long.class,Bar.class,"id",true);
|
||||
@@ -290,7 +331,11 @@ public class SetPropertiesTest extends XWorkTestCase {
|
||||
public Object create(Context context) throws Exception {
|
||||
return determiner;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public Class type() {
|
||||
return determiner.getClass();
|
||||
}
|
||||
}, Scope.SINGLETON);
|
||||
}
|
||||
});
|
||||
|
||||
+41
@@ -22,6 +22,8 @@ import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.XWorkTestCase;
|
||||
import com.opensymphony.xwork2.util.ListHolder;
|
||||
import com.opensymphony.xwork2.util.ValueStack;
|
||||
import ognl.ListPropertyAccessor;
|
||||
import ognl.PropertyAccessor;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -61,4 +63,43 @@ public class XWorkListPropertyAccessorTest extends XWorkTestCase {
|
||||
assertEquals(new Integer(myList.size()), vs.findValue("strings.size()"));
|
||||
assertEquals(new Integer(myList.size()), vs.findValue("strings.size"));
|
||||
}
|
||||
|
||||
public void testAutoGrowthCollectionLimit() {
|
||||
PropertyAccessor accessor = container.getInstance(PropertyAccessor.class, ArrayList.class.getName());
|
||||
((XWorkListPropertyAccessor) accessor).setAutoGrowCollectionLimit("2");
|
||||
|
||||
List<String> myList = new ArrayList<>();
|
||||
ListHolder listHolder = new ListHolder();
|
||||
listHolder.setStrings(myList);
|
||||
|
||||
ValueStack vs = ActionContext.getContext().getValueStack();
|
||||
vs.push(listHolder);
|
||||
|
||||
vs.setValue("strings[0]", "a");
|
||||
vs.setValue("strings[1]", "b");
|
||||
vs.setValue("strings[2]", "c");
|
||||
vs.setValue("strings[3]", "d");
|
||||
|
||||
assertEquals(3, vs.findValue("strings.size()"));
|
||||
}
|
||||
|
||||
public void testDeprecatedAutoGrowCollectionLimit() {
|
||||
PropertyAccessor accessor = container.getInstance(PropertyAccessor.class, ArrayList.class.getName());
|
||||
((XWorkListPropertyAccessor) accessor).setDeprecatedAutoGrowCollectionLimit("2");
|
||||
|
||||
List<String> myList = new ArrayList<>();
|
||||
ListHolder listHolder = new ListHolder();
|
||||
listHolder.setStrings(myList);
|
||||
|
||||
ValueStack vs = ActionContext.getContext().getValueStack();
|
||||
vs.push(listHolder);
|
||||
|
||||
vs.setValue("strings[0]", "a");
|
||||
vs.setValue("strings[1]", "b");
|
||||
vs.setValue("strings[2]", "c");
|
||||
vs.setValue("strings[3]", "d");
|
||||
|
||||
assertEquals(3, vs.findValue("strings.size()"));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
-8
@@ -86,12 +86,4 @@ public class TestActionInvocation implements ActionInvocation {
|
||||
public void init(ActionProxy proxy) {
|
||||
}
|
||||
|
||||
public ActionInvocation serialize() {
|
||||
return this;
|
||||
}
|
||||
|
||||
public ActionInvocation deserialize(ActionContext actionContext) {
|
||||
return this;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -32,7 +32,7 @@ import java.util.List;
|
||||
converterClass=AddressTypeConverter.class),
|
||||
@TypeConversion(type=ConversionType.APPLICATION,
|
||||
key="com.opensymphony.xwork2.test.annotations.Person",
|
||||
converterClass=PersonTypeConverter.class)})
|
||||
converter="com.opensymphony.xwork2.test.annotations.PersonTypeConverter")})
|
||||
public class PersonAction {
|
||||
List<Person> users;
|
||||
private List<Address> address;
|
||||
|
||||
@@ -19,14 +19,19 @@
|
||||
package com.opensymphony.xwork2.util;
|
||||
|
||||
import com.opensymphony.xwork2.util.annotation.Dummy2Class;
|
||||
import com.opensymphony.xwork2.util.annotation.Dummy3Class;
|
||||
import com.opensymphony.xwork2.util.annotation.DummyClass;
|
||||
import com.opensymphony.xwork2.util.annotation.DummyClassExt;
|
||||
import com.opensymphony.xwork2.util.annotation.MyAnnotation;
|
||||
|
||||
import com.opensymphony.xwork2.util.annotation.MyAnnotation2;
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* @author Dan Oxlade, dan d0t oxlade at gmail d0t c0m
|
||||
*/
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import static org.fest.assertions.Assertions.assertThat;
|
||||
|
||||
public class AnnotationUtilsTest extends TestCase {
|
||||
|
||||
public void testFindAnnotationOnClass() {
|
||||
@@ -41,4 +46,25 @@ public class AnnotationUtilsTest extends TestCase {
|
||||
assertEquals("package-test", ns.value());
|
||||
}
|
||||
|
||||
public void testFindAnnotationOnParents() {
|
||||
MyAnnotation2 ns = AnnotationUtils.findAnnotation(Dummy3Class.class, MyAnnotation2.class);
|
||||
assertNotNull(ns);
|
||||
assertEquals("abstract-abstract", ns.value());
|
||||
}
|
||||
|
||||
public void testFindAnnotationsOnAll() {
|
||||
List<MyAnnotation> annotations = AnnotationUtils.findAnnotations(DummyClassExt.class, MyAnnotation.class);
|
||||
|
||||
assertThat(annotations)
|
||||
.isNotNull()
|
||||
.isNotEmpty()
|
||||
.hasSize(5);
|
||||
|
||||
Set<String> values = new HashSet<>();
|
||||
for (MyAnnotation annotation : annotations) {
|
||||
values.add(annotation.value());
|
||||
}
|
||||
assertThat(values).contains("class-test", "package-test", "interface-test", "package2-test");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,10 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2.util;
|
||||
|
||||
import com.opensymphony.xwork2.conversion.annotations.ConversionRule;
|
||||
import com.opensymphony.xwork2.conversion.annotations.ConversionType;
|
||||
import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
|
||||
@@ -34,9 +38,11 @@ public class Foo {
|
||||
Date meeting;
|
||||
Foo child;
|
||||
List cats;
|
||||
List annotatedCats;
|
||||
List moreCats;
|
||||
List strings;
|
||||
Collection barCollection;
|
||||
Collection annotatedBarCollection;
|
||||
Map catMap;
|
||||
Map anotherCatMap;
|
||||
String title;
|
||||
@@ -96,6 +102,15 @@ public class Foo {
|
||||
return cats;
|
||||
}
|
||||
|
||||
public void setAnnotatedCats(List annotatedCats) {
|
||||
this.annotatedCats = annotatedCats;
|
||||
}
|
||||
|
||||
@TypeConversion(rule = ConversionRule.ELEMENT, converterClass = Cat.class)
|
||||
public List getAnnotatedCats() {
|
||||
return annotatedCats;
|
||||
}
|
||||
|
||||
public void setChild(Foo child) {
|
||||
this.child = child;
|
||||
}
|
||||
@@ -154,6 +169,16 @@ public class Foo {
|
||||
this.barCollection = barCollection;
|
||||
}
|
||||
|
||||
@TypeConversion(rule = ConversionRule.KEY_PROPERTY, value = "id")
|
||||
public void setAnnotatedBarCollection(Collection annotatedBarCollection) {
|
||||
this.annotatedBarCollection = annotatedBarCollection;
|
||||
}
|
||||
|
||||
@TypeConversion(rule = ConversionRule.ELEMENT, converter = "com.opensymphony.xwork2.util.Bar")
|
||||
public Collection getAnnotatedBarCollection() {
|
||||
return annotatedBarCollection;
|
||||
}
|
||||
|
||||
public void setPoints(long[] points) {
|
||||
this.points = points;
|
||||
}
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
package com.opensymphony.xwork2.util;
|
||||
|
||||
import com.opensymphony.xwork2.Action;
|
||||
import com.opensymphony.xwork2.conversion.annotations.Conversion;
|
||||
import com.opensymphony.xwork2.conversion.annotations.ConversionRule;
|
||||
import com.opensymphony.xwork2.conversion.annotations.ConversionType;
|
||||
import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@@ -30,10 +34,19 @@ import java.util.Map;
|
||||
*
|
||||
* @author Rainer Hermanns
|
||||
*/
|
||||
@Conversion(
|
||||
conversions= {
|
||||
@TypeConversion(key = "KeyProperty_annotatedBeanMap", rule = ConversionRule.KEY_PROPERTY, value = "id"),
|
||||
@TypeConversion(key = "Element_annotatedBeanMap", rule = ConversionRule.ELEMENT, converterClass = MyBean.class),
|
||||
@TypeConversion(key = "KeyProperty_annotatedBeanList", rule = ConversionRule.KEY_PROPERTY, value = "id"),
|
||||
@TypeConversion(key = "Element_annotatedBeanList", rule = ConversionRule.ELEMENT, converterClass = MyBean.class)
|
||||
})
|
||||
public class MyBeanAction implements Action {
|
||||
|
||||
private List beanList = new ArrayList();
|
||||
private Map beanMap = new HashMap();
|
||||
private Map annotatedBeanMap = new HashMap();
|
||||
private List annotatedBeanList = new ArrayList();
|
||||
|
||||
public List getBeanList() {
|
||||
return beanList;
|
||||
@@ -51,6 +64,24 @@ public class MyBeanAction implements Action {
|
||||
this.beanMap = beanMap;
|
||||
}
|
||||
|
||||
public Map getAnnotatedBeanMap() {
|
||||
return annotatedBeanMap;
|
||||
}
|
||||
|
||||
@TypeConversion(rule = ConversionRule.KEY, converterClass = Long.class)
|
||||
public void setAnnotatedBeanMap(Map annotatedBeanMap) {
|
||||
this.annotatedBeanMap = annotatedBeanMap;
|
||||
}
|
||||
|
||||
public List getAnnotatedBeanList() {
|
||||
return annotatedBeanList;
|
||||
}
|
||||
|
||||
@TypeConversion(rule = ConversionRule.CREATE_IF_NULL, value = "true")
|
||||
public void setAnnotatedBeanList(List annotatedBeanList) {
|
||||
this.annotatedBeanList = annotatedBeanList;
|
||||
}
|
||||
|
||||
public String execute() throws Exception {
|
||||
return SUCCESS;
|
||||
}
|
||||
|
||||
@@ -39,6 +39,9 @@ public class MyBeanActionTest extends XWorkTestCase {
|
||||
params.put("beanList(1234567890).name", "This is the bla bean");
|
||||
params.put("beanList(1234567891).name", "This is the 2nd bla bean");
|
||||
|
||||
params.put("annotatedBeanList(1234567890).name", "This is the bla bean by annotation");
|
||||
params.put("annotatedBeanList(1234567891).name", "This is the 2nd bla bean by annotation");
|
||||
|
||||
HashMap<String, Object> extraContext = new HashMap<>();
|
||||
extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
|
||||
|
||||
@@ -53,6 +56,15 @@ public class MyBeanActionTest extends XWorkTestCase {
|
||||
assertEquals(new Long(1234567890), Long.valueOf(proxy.getInvocation().getStack().findValue("beanList.get(0).id").toString()));
|
||||
assertEquals("This is the 2nd bla bean", proxy.getInvocation().getStack().findValue("beanList.get(1).name"));
|
||||
assertEquals(new Long(1234567891), Long.valueOf(proxy.getInvocation().getStack().findValue("beanList.get(1).id").toString()));
|
||||
|
||||
assertEquals(2, Integer.parseInt(proxy.getInvocation().getStack().findValue("annotatedBeanList.size").toString()));
|
||||
assertEquals(MyBean.class.getName(), proxy.getInvocation().getStack().findValue("annotatedBeanList.get(0)").getClass().getName());
|
||||
assertEquals(MyBean.class.getName(), proxy.getInvocation().getStack().findValue("annotatedBeanList.get(1)").getClass().getName());
|
||||
|
||||
assertEquals("This is the bla bean by annotation", proxy.getInvocation().getStack().findValue("annotatedBeanList.get(0).name"));
|
||||
assertEquals(new Long(1234567890), Long.valueOf(proxy.getInvocation().getStack().findValue("annotatedBeanList.get(0).id").toString()));
|
||||
assertEquals("This is the 2nd bla bean by annotation", proxy.getInvocation().getStack().findValue("annotatedBeanList.get(1).name"));
|
||||
assertEquals(new Long(1234567891), Long.valueOf(proxy.getInvocation().getStack().findValue("annotatedBeanList.get(1).id").toString()));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
@@ -67,6 +79,12 @@ public class MyBeanActionTest extends XWorkTestCase {
|
||||
params.put("beanMap[1234567890].name", "This is the bla bean");
|
||||
params.put("beanMap[1234567891].name", "This is the 2nd bla bean");
|
||||
|
||||
params.put("annotatedBeanMap[1234567890].id", "1234567890");
|
||||
params.put("annotatedBeanMap[1234567891].id", "1234567891");
|
||||
|
||||
params.put("annotatedBeanMap[1234567890].name", "This is the bla bean by annotation");
|
||||
params.put("annotatedBeanMap[1234567891].name", "This is the 2nd bla bean by annotation");
|
||||
|
||||
HashMap<String, Object> extraContext = new HashMap<>();
|
||||
extraContext.put(ActionContext.PARAMETERS, HttpParameters.create(params).build());
|
||||
|
||||
@@ -89,6 +107,21 @@ public class MyBeanActionTest extends XWorkTestCase {
|
||||
|
||||
assertEquals("1234567890", proxy.getInvocation().getStack().findValue("beanMap.get(1234567890L).id").toString());
|
||||
assertEquals("1234567891", proxy.getInvocation().getStack().findValue("beanMap.get(1234567891L).id").toString());
|
||||
|
||||
assertEquals(2, Integer.parseInt(proxy.getInvocation().getStack().findValue("annotatedBeanMap.size").toString()));
|
||||
|
||||
assertEquals(true, action.getAnnotatedBeanMap().containsKey(1234567890L));
|
||||
assertEquals(true, action.getAnnotatedBeanMap().containsKey(1234567891L));
|
||||
|
||||
|
||||
assertEquals(MyBean.class.getName(), proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567890L)").getClass().getName());
|
||||
assertEquals(MyBean.class.getName(), proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567891L)").getClass().getName());
|
||||
|
||||
assertEquals("This is the bla bean by annotation", proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567890L).name"));
|
||||
assertEquals("This is the 2nd bla bean by annotation", proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567891L).name"));
|
||||
|
||||
assertEquals("1234567890", proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567890L).id").toString());
|
||||
assertEquals("1234567891", proxy.getInvocation().getStack().findValue("annotatedBeanMap.get(1234567891L).id").toString());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
fail();
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.util.annotation;
|
||||
|
||||
import com.opensymphony.xwork2.util.annotation.pkg1.AbstractDummyAction;
|
||||
|
||||
public class Dummy3Class extends AbstractDummyAction{
|
||||
|
||||
}
|
||||
@@ -18,8 +18,10 @@
|
||||
*/
|
||||
package com.opensymphony.xwork2.util.annotation;
|
||||
|
||||
import com.opensymphony.xwork2.util.annotation.pkg2.Package2DummyInterface;
|
||||
|
||||
@MyAnnotation("class-test")
|
||||
public class DummyClass {
|
||||
public class DummyClass implements Package2DummyInterface {
|
||||
|
||||
public DummyClass() {
|
||||
}
|
||||
|
||||
@@ -23,4 +23,6 @@ import java.lang.annotation.RetentionPolicy;
|
||||
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface MyAnnotation2 {
|
||||
|
||||
String value() default "";
|
||||
}
|
||||
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.util.annotation.pkg1;
|
||||
|
||||
import com.opensymphony.xwork2.util.annotation.MyAnnotation2;
|
||||
|
||||
@MyAnnotation2("abstract-abstract")
|
||||
public class AbstractAbstractDummyAction {
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.util.annotation.pkg1;
|
||||
|
||||
public class AbstractDummyAction extends AbstractAbstractDummyAction {
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package com.opensymphony.xwork2.util.annotation.pkg2;
|
||||
|
||||
import com.opensymphony.xwork2.util.annotation.MyAnnotation;
|
||||
|
||||
@MyAnnotation("interface-test")
|
||||
public interface Package2DummyInterface {
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user