mirror of
https://github.com/apache/struts.git
synced 2026-08-05 14:47:09 +00:00
WW-2922 move convention plugin out of sandbox
git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@727418 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -0,0 +1,39 @@
|
||||
Design
|
||||
|
||||
Action with no annotations (all the default handlings)
|
||||
--------------------------
|
||||
|
||||
Action name is class name.
|
||||
Action package is based on the either any Namespace annotations on the class or Java package the
|
||||
action class is defined in or the Java package name and the root Java package, which is determined
|
||||
based on the package locators or the action package list. In either case, a root package is
|
||||
identified and the namespace is the packages below the root up to and including the package that
|
||||
contains the action class.
|
||||
Action method is execute in all cases.
|
||||
Results are built first from the Result annotations at the class level. Next, they are built from
|
||||
the resources available in the web application and in the classpath based on the result location,
|
||||
namespace of the action and action name (not anything to do with the code element names). Results
|
||||
are found for common result codes including, success, error, input, failure, etc. If a specific
|
||||
result doesn't exist using the result code then just the action namespace and action name are used to
|
||||
locate results. If there are still no results found, than a redirect is added back to the index
|
||||
action for the namespace, if one exists.
|
||||
|
||||
Action with Action(s) annotations
|
||||
---------------------------------
|
||||
|
||||
If the annotation is located on any method other than execute, than the action configuration built
|
||||
from the annotation is in addition to the action configuration built using the default. Unless there
|
||||
is an annotation that contains no value, in which case, the method that annotation is defined for
|
||||
becomes the default action method. If the annotation is defined on the execute method, regardless of
|
||||
the value of the annotation, no default configuration is built for the class.
|
||||
If multiple annotations have no value, an error should occur.
|
||||
If multiple annotations have the same value, an error should occur.
|
||||
|
||||
Action name is taken from the annotation value. If the value is empty, the default action name
|
||||
is used.
|
||||
Action package is taken from the annotation value. If the annotation value doesn't start with a slash
|
||||
character, the default action namespace is used.
|
||||
Action method is always the method that the annotation is defined on.
|
||||
Results are built first from the array of Results on the Action annotation. Next, they are built
|
||||
from the class level Result annotations. Lastly, all default results are created. All Results already
|
||||
created during this process should not be overridden later in the process.
|
||||
@@ -0,0 +1,91 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
<project xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-plugins</artifactId>
|
||||
<version>2.1.3-SNAPSHOT</version>
|
||||
</parent>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-convention-plugin</artifactId>
|
||||
<packaging>jar</packaging>
|
||||
<name>Struts 2 Convention Plugin</name>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-convention-plugin</connection>
|
||||
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-convention-plugin</developerConnection>
|
||||
<url>http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/struts2-convention-plugin</url>
|
||||
</scm>
|
||||
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<inherited>true</inherited>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-source-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>attach-sources</id>
|
||||
<goals>
|
||||
<goal>jar</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.apache.struts</groupId>
|
||||
<artifactId>struts2-core</artifactId>
|
||||
<version>2.1.3-SNAPSHOT</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<scope>test</scope>
|
||||
<version>3.8.1</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.easymock</groupId>
|
||||
<artifactId>easymock</artifactId>
|
||||
<version>2.3</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>servlet-api</artifactId>
|
||||
<version>2.4</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>javax.servlet</groupId>
|
||||
<artifactId>jsp-api</artifactId>
|
||||
<version>2.0</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
</project>
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface defines how the action configurations for the current
|
||||
* web application can be constructed. This must find all actions that
|
||||
* are not specifically defined in the struts XML files or any plugins.
|
||||
* Furthermore, it must make every effort to locate all action results
|
||||
* as well.
|
||||
* </p>
|
||||
*/
|
||||
public interface ActionConfigBuilder {
|
||||
/**
|
||||
* Builds all the action configurations and stores them into the XWork configuration instance
|
||||
* via XWork dependency injetion.
|
||||
*/
|
||||
void buildActionConfigs();
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface defines the method that is used to create action
|
||||
* names based on the name of a class.
|
||||
* </p>
|
||||
*/
|
||||
public interface ActionNameBuilder {
|
||||
/**
|
||||
* Given the name of the class, this method should build an action name.
|
||||
*
|
||||
* @param className The class name.
|
||||
* @return The action name and never null.
|
||||
*/
|
||||
String build(String className);
|
||||
}
|
||||
+81
@@ -0,0 +1,81 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import com.opensymphony.xwork2.config.Configuration;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.config.ConfigurationProvider;
|
||||
import com.opensymphony.xwork2.inject.ContainerBuilder;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.location.LocatableProperties;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class is a configuration provider for the XWork configuration
|
||||
* system. This is really the only way to truly handle loading of the
|
||||
* packages, actions and results correctly. This doesn't contain any
|
||||
* logic and instead delegates to the configured instance of the
|
||||
* {@link ActionConfigBuilder} interface.
|
||||
* </p>
|
||||
*/
|
||||
public class ClasspathConfigurationProvider implements ConfigurationProvider {
|
||||
private ActionConfigBuilder actionConfigBuilder;
|
||||
|
||||
@Inject
|
||||
public ClasspathConfigurationProvider(ActionConfigBuilder actionConfigBuilder) {
|
||||
this.actionConfigBuilder = actionConfigBuilder;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not used.
|
||||
*/
|
||||
public void destroy() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Not used.
|
||||
*/
|
||||
public void init(Configuration configuration) {
|
||||
}
|
||||
|
||||
/**
|
||||
* Does nothing.
|
||||
*/
|
||||
public void register(ContainerBuilder containerBuilder, LocatableProperties locatableProperties)
|
||||
throws ConfigurationException {
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the packages using the {@link ActionConfigBuilder}.
|
||||
*
|
||||
* @throws ConfigurationException
|
||||
*/
|
||||
public void loadPackages() throws ConfigurationException {
|
||||
actionConfigBuilder.buildActionConfigs();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Always false.
|
||||
*/
|
||||
public boolean needsReload() {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
+418
@@ -0,0 +1,418 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.net.MalformedURLException;
|
||||
import java.util.HashMap;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.struts2.util.ClassLoaderUtils;
|
||||
|
||||
import com.opensymphony.xwork2.Action;
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.ActionSupport;
|
||||
import com.opensymphony.xwork2.ObjectFactory;
|
||||
import com.opensymphony.xwork2.Result;
|
||||
import com.opensymphony.xwork2.UnknownHandler;
|
||||
import com.opensymphony.xwork2.XWorkException;
|
||||
import com.opensymphony.xwork2.config.Configuration;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class is the default unknown handler for all of the Convention
|
||||
* plugin integration with XWork. This handles instances when a URL doesn't
|
||||
* have an action associated with it but does a viable result and also the
|
||||
* instance where an action returns a result code that isn't already
|
||||
* configured but there is a viable result for the code.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This class also handles all of the index actions using redirects
|
||||
* and actions in nested packages. For example, if there is an action
|
||||
* <strong>/foo/index</strong> and the URL <strong>/foo</strong> is used,
|
||||
* this will render the index action in the /foo namespace.
|
||||
* </p>
|
||||
*/
|
||||
public class ConventionUnknownHandler implements UnknownHandler {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(ConventionUnknownHandler.class);
|
||||
protected Configuration configuration;
|
||||
protected ObjectFactory objectFactory;
|
||||
protected ServletContext servletContext;
|
||||
protected ResultMapBuilder resultMapBuilder;
|
||||
protected String defaultParentPackageName;
|
||||
protected PackageConfig parentPackage;
|
||||
|
||||
private boolean redirectToSlash;
|
||||
private ConventionsService conventionsService;
|
||||
private String nameSeparator;
|
||||
|
||||
/**
|
||||
* Constructs the unknown handler.
|
||||
*
|
||||
* @param configuration The XWork configuration.
|
||||
* @param objectFactory The XWork object factory used to create result instances.
|
||||
* @param servletContext The servlet context used to help build the action configurations.
|
||||
* @param resultMapBuilder The result map builder that is used to create results.
|
||||
* @param conventionsService The conventions service used to get all the conventions and
|
||||
* configurations.
|
||||
* @param defaultParentPackageName The default XWork package that the unknown handler will use as
|
||||
* the parent package for new actions and results.
|
||||
* @param redirectToSlash A boolean parameter that controls whether or not this will handle
|
||||
* unknown actions in the same manner as Apache, Tomcat and other web servers. This
|
||||
* handling will send back a redirect for URLs such as /foo to /foo/ if there doesn't
|
||||
* exist an action that responds to /foo.
|
||||
* @param nameSeparator The character used as word separator in the action names. "-" by default
|
||||
*/
|
||||
@Inject
|
||||
public ConventionUnknownHandler(Configuration configuration, ObjectFactory objectFactory,
|
||||
ServletContext servletContext, ResultMapBuilder resultMapBuilder,
|
||||
ConventionsService conventionsService,
|
||||
@Inject("struts.convention.default.parent.package") String defaultParentPackageName,
|
||||
@Inject("struts.convention.redirect.to.slash") String redirectToSlash,
|
||||
@Inject("struts.convention.action.name.separator") String nameSeparator) {
|
||||
this.configuration = configuration;
|
||||
this.objectFactory = objectFactory;
|
||||
this.servletContext = servletContext;
|
||||
this.resultMapBuilder = resultMapBuilder;
|
||||
this.conventionsService = conventionsService;
|
||||
this.defaultParentPackageName = defaultParentPackageName;
|
||||
this.nameSeparator = nameSeparator;
|
||||
|
||||
this.parentPackage = configuration.getPackageConfig(defaultParentPackageName);
|
||||
if (parentPackage == null) {
|
||||
throw new ConfigurationException("Unknown default parent package [" + defaultParentPackageName + "]");
|
||||
}
|
||||
|
||||
this.redirectToSlash = Boolean.parseBoolean(redirectToSlash);
|
||||
}
|
||||
|
||||
public ActionConfig handleUnknownAction(String namespace, String actionName)
|
||||
throws XWorkException {
|
||||
// Strip the namespace if it is just a slash
|
||||
if (namespace == null || "/".equals(namespace)) {
|
||||
namespace = "";
|
||||
}
|
||||
|
||||
Map<String, ResultTypeConfig> resultsByExtension = conventionsService.getResultTypesByExtension(parentPackage);
|
||||
String pathPrefix = determinePath(null, namespace);
|
||||
ActionConfig actionConfig = null;
|
||||
|
||||
// Try /idx/action.jsp if actionName is not empty, otherwise it will just be /.jsp
|
||||
if (!actionName.equals("")) {
|
||||
Resource resource = findResource(resultsByExtension, pathPrefix, actionName);
|
||||
if (resource != null) {
|
||||
actionConfig = buildActionConfig(resource.path, resultsByExtension.get(resource.ext));
|
||||
}
|
||||
}
|
||||
|
||||
if (actionConfig == null) {
|
||||
Resource resource = findResource(resultsByExtension, pathPrefix, actionName, "/index");
|
||||
|
||||
// If the URL is /foo and there is an action we can redirect to, send the redirect to /foo/.
|
||||
// However, if that action is not in the same namespace, it is the default, so I'm not going
|
||||
// to return that.
|
||||
if (!actionName.equals("") && redirectToSlash) {
|
||||
ResultTypeConfig redirectResultTypeConfig = parentPackage.getAllResultTypeConfigs().get("redirect");
|
||||
String redirectNamespace = namespace + "/" + actionName;
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Checking if there is an action named index in the namespace [#0]",
|
||||
redirectNamespace);
|
||||
}
|
||||
|
||||
actionConfig = configuration.getRuntimeConfiguration().getActionConfig(redirectNamespace, "index");
|
||||
if (actionConfig != null) {
|
||||
if (LOG.isTraceEnabled())
|
||||
LOG.trace("Found action config");
|
||||
|
||||
PackageConfig packageConfig = configuration.getPackageConfig(actionConfig.getPackageName());
|
||||
if (redirectNamespace.equals(packageConfig.getNamespace())) {
|
||||
if (LOG.isTraceEnabled())
|
||||
LOG.trace("Action is not a default - redirecting");
|
||||
return buildActionConfig(redirectNamespace + "/", redirectResultTypeConfig);
|
||||
}
|
||||
|
||||
if (LOG.isTraceEnabled())
|
||||
LOG.trace("Action was a default - NOT redirecting");
|
||||
}
|
||||
|
||||
if (resource != null) {
|
||||
return buildActionConfig(redirectNamespace + "/", redirectResultTypeConfig);
|
||||
}
|
||||
}
|
||||
|
||||
if (resource != null) {
|
||||
// Otherwise, if the URL is /foo or /foo/ look for index pages in /foo/
|
||||
actionConfig = buildActionConfig(resource.path, resultsByExtension.get(resource.ext));
|
||||
}
|
||||
}
|
||||
|
||||
return actionConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds a resource using the given path parts and all of the extensions in the map.
|
||||
*
|
||||
* @param resultsByExtension Map of extension to result type config objects.
|
||||
* @param parts The parts of the resource.
|
||||
* @return The resource path or null.
|
||||
*/
|
||||
protected Resource findResource(Map<String, ResultTypeConfig> resultsByExtension, String... parts) {
|
||||
for (String ext : resultsByExtension.keySet()) {
|
||||
String path = string(parts) + "." + ext;
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Checking for [#0]", path);
|
||||
}
|
||||
|
||||
try {
|
||||
if (servletContext.getResource(path) != null) {
|
||||
return new Resource(path, ext);
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
if (LOG.isErrorEnabled())
|
||||
LOG.error("Unable to parse path to the web application resource [#0] skipping...", path);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected ActionConfig buildActionConfig(String path, ResultTypeConfig resultTypeConfig) {
|
||||
Map<String, ResultConfig> results = new HashMap<String,ResultConfig>();
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
if (resultTypeConfig.getParams() != null) {
|
||||
params.putAll(resultTypeConfig.getParams());
|
||||
}
|
||||
params.put(resultTypeConfig.getDefaultResultParam(), path);
|
||||
|
||||
// PackageConfig pkg = configuration.getPackageConfig(defaultParentPackageName);
|
||||
// List<InterceptorMapping> interceptors = InterceptorBuilder.constructInterceptorReference(pkg,
|
||||
// pkg.getFullDefaultInterceptorRef(), Collections.EMPTY_MAP, null, objectFactory);
|
||||
ResultConfig config = new ResultConfig.Builder(Action.SUCCESS, resultTypeConfig.getClassName()).
|
||||
addParams(params).build();
|
||||
results.put(Action.SUCCESS, config);
|
||||
|
||||
//addInterceptors(interceptors).
|
||||
return new ActionConfig.Builder(defaultParentPackageName, "execute", ActionSupport.class.getName()).
|
||||
addResultConfigs(results).build();
|
||||
}
|
||||
|
||||
private Result scanResultsByExtension(String ns, String actionName, String pathPrefix,
|
||||
String resultCode, ActionContext actionContext) {
|
||||
Map<String, ResultTypeConfig> resultsByExtension = conventionsService.getResultTypesByExtension(parentPackage);
|
||||
Result result = null;
|
||||
for (String ext : resultsByExtension.keySet()) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
String fqan = ns + "/" + actionName;
|
||||
LOG.trace("Trying to locate the correct result for the FQ action [#0]"
|
||||
+ " with an file extension of [#1] in the directory [#2] " + "and a result code of [#3]",
|
||||
fqan, ext, pathPrefix, resultCode);
|
||||
}
|
||||
|
||||
String path = string(pathPrefix, actionName, nameSeparator, resultCode, "." , ext);
|
||||
result = findResult(path, resultCode, ext, actionContext, resultsByExtension);
|
||||
if (result != null) {
|
||||
break;
|
||||
}
|
||||
|
||||
path = string(pathPrefix, actionName, "." , ext);
|
||||
result = findResult(path, resultCode, ext, actionContext, resultsByExtension);
|
||||
if (result != null) {
|
||||
break;
|
||||
}
|
||||
|
||||
// Issue #6 - Scan for result-code as page name
|
||||
path = string(pathPrefix, resultCode, "." , ext);
|
||||
result = findResult(path, resultCode, ext, actionContext, resultsByExtension);
|
||||
if (result != null) {
|
||||
break;
|
||||
}
|
||||
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public Result handleUnknownResult(ActionContext actionContext, String actionName,
|
||||
ActionConfig actionConfig, String resultCode) throws XWorkException {
|
||||
|
||||
PackageConfig pkg = configuration.getPackageConfig(actionConfig.getPackageName());
|
||||
String ns = pkg.getNamespace();
|
||||
String pathPrefix = determinePath(actionConfig, ns);
|
||||
|
||||
Result result = scanResultsByExtension(ns, actionName, pathPrefix, resultCode, actionContext);
|
||||
|
||||
if (result == null) {
|
||||
// Try /idx/action/index.jsp
|
||||
Map<String, ResultTypeConfig> resultsByExtension = conventionsService.getResultTypesByExtension(pkg);
|
||||
for (String ext : resultsByExtension.keySet()) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
String fqan = ns + "/" + actionName;
|
||||
LOG.trace("Checking for [#0/index.#1]", fqan, ext);
|
||||
}
|
||||
|
||||
String path = string(pathPrefix, actionName, "/index", nameSeparator, resultCode, ".", ext);
|
||||
result = findResult(path, resultCode, ext, actionContext, resultsByExtension);
|
||||
if (result != null) {
|
||||
break;
|
||||
}
|
||||
|
||||
path = string(pathPrefix, actionName, "/index." , ext);
|
||||
result = findResult(path, resultCode, ext, actionContext, resultsByExtension);
|
||||
if (result != null) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (result == null && resultCode != null) {
|
||||
//try to find an action to chain to. If the source action is "foo" and
|
||||
//the result is "bar", we will try to find an action called "foo-bar"
|
||||
//in the same package
|
||||
String chainedTo = new StringBuilder(actionName).append(nameSeparator).append(resultCode).toString();
|
||||
ActionConfig chainedToConfig = pkg.getActionConfigs().get(chainedTo);
|
||||
if (chainedToConfig != null) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Action [#0] used as chain result for [#1] and result [#2]", chainedTo, actionName, resultCode);
|
||||
}
|
||||
|
||||
ResultTypeConfig chainResultType = pkg.getAllResultTypeConfigs().get("chain");
|
||||
result = buildResult(chainedTo, resultCode, chainResultType, actionContext);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
protected Result findResult(String path, String resultCode, String ext, ActionContext actionContext,
|
||||
Map<String, ResultTypeConfig> resultsByExtension) {
|
||||
try {
|
||||
boolean traceEnabled = LOG.isTraceEnabled();
|
||||
if (traceEnabled)
|
||||
LOG.trace("Checking ServletContext for [#0]", path);
|
||||
|
||||
if (servletContext.getResource(path) != null) {
|
||||
if (traceEnabled)
|
||||
LOG.trace("Found");
|
||||
return buildResult(path, resultCode, resultsByExtension.get(ext), actionContext);
|
||||
}
|
||||
|
||||
if (traceEnabled)
|
||||
LOG.trace("Checking ClasLoader for #0", path);
|
||||
|
||||
String classLoaderPath = path.startsWith("/") ? path.substring(1, path.length()) : path;
|
||||
if (ClassLoaderUtils.getResource(classLoaderPath, getClass()) != null) {
|
||||
if (traceEnabled)
|
||||
LOG.trace("Found");
|
||||
return buildResult(path, resultCode, resultsByExtension.get(ext), actionContext);
|
||||
}
|
||||
} catch (MalformedURLException e) {
|
||||
if (LOG.isErrorEnabled())
|
||||
LOG.error("Unable to parse template path: [#0] skipping...", path);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
protected Result buildResult(String path, String resultCode, ResultTypeConfig config, ActionContext invocationContext) {
|
||||
String resultClass = config.getClassName();
|
||||
|
||||
Map<String,String> params = new LinkedHashMap<String,String>();
|
||||
if (config.getParams() != null) {
|
||||
params.putAll(config.getParams());
|
||||
}
|
||||
params.put(config.getDefaultResultParam(), path);
|
||||
|
||||
ResultConfig resultConfig = new ResultConfig.Builder(resultCode, resultClass).addParams(params).build();
|
||||
try {
|
||||
return objectFactory.buildResult(resultConfig, invocationContext.getContextMap());
|
||||
} catch (Exception e) {
|
||||
throw new XWorkException("Unable to build convention result", e, resultConfig);
|
||||
}
|
||||
}
|
||||
|
||||
protected String string(String... parts) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (String part : parts) {
|
||||
sb.append(part);
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the result path prefix that the request URL is for, minus the action name. This includes
|
||||
* the base result location and the namespace, with all the slashes handled.
|
||||
*
|
||||
* @param actionConfig (Optional) The might be a ConventionActionConfig, from which we can get the
|
||||
* default base result location of that specific action.
|
||||
* @param namespace The current URL namespace.
|
||||
* @return The path prefix and never null.
|
||||
*/
|
||||
protected String determinePath(ActionConfig actionConfig, String namespace) {
|
||||
String finalPrefix = conventionsService.determineResultPath(actionConfig);
|
||||
|
||||
if (!finalPrefix.endsWith("/")) {
|
||||
finalPrefix += "/";
|
||||
}
|
||||
|
||||
if (namespace == null || "/".equals(namespace)) {
|
||||
namespace = "";
|
||||
}
|
||||
|
||||
if (namespace.length() > 0) {
|
||||
if (namespace.startsWith("/")) {
|
||||
namespace = namespace.substring(1);
|
||||
}
|
||||
|
||||
if (!namespace.endsWith("/")) {
|
||||
namespace += "/";
|
||||
}
|
||||
}
|
||||
|
||||
return finalPrefix + namespace;
|
||||
}
|
||||
|
||||
/**
|
||||
* Not used
|
||||
*/
|
||||
public Object handleUnknownActionMethod(Object action, String methodName) throws NoSuchMethodException {
|
||||
throw new NoSuchMethodException();
|
||||
}
|
||||
|
||||
public static class Resource {
|
||||
final String path;
|
||||
final String ext;
|
||||
|
||||
public Resource(String path, String ext) {
|
||||
this.path = path;
|
||||
this.ext = ext;
|
||||
}
|
||||
}
|
||||
}
|
||||
+67
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface defines the conventions that are used by the convention plugin.
|
||||
* In most cases the methods on this class will provide the best default for any
|
||||
* values and also handle locating overrides of the default via the annotations
|
||||
* that are part of the plugin.
|
||||
* </p>
|
||||
*/
|
||||
public interface ConventionsService {
|
||||
/**
|
||||
* Locates the result location from annotations on the action class or the package or returns the
|
||||
* default if no annotations are present.
|
||||
*
|
||||
* @param actionClass The action class.
|
||||
* @return The result location if it is set in the annotations. Otherwise, the default result
|
||||
* location is returned.
|
||||
*/
|
||||
String determineResultPath(Class<?> actionClass);
|
||||
|
||||
/**
|
||||
* Delegates to the other method but first looks up the Action's class using the given class name.
|
||||
*
|
||||
* @param actionConfig (Optional) The configuration for the action that the result is being
|
||||
* built for or null if the default result path is needed.
|
||||
* @return The result location if it is set in the annotations for the class of the ActionConfig.
|
||||
* Otherwise, the default result location is returned. If null is passed in, the default
|
||||
* is returned,
|
||||
*/
|
||||
String determineResultPath(ActionConfig actionConfig);
|
||||
|
||||
/**
|
||||
* Returns a mapping between the result type strings and the {@link ResultTypeConfig} instances
|
||||
* based on the {@link PackageConfig} given.
|
||||
*
|
||||
* @param packageConfig The PackageConfig to get the result types for.
|
||||
* @return The result types or an empty Map of nothing is configured.
|
||||
*/
|
||||
Map<String, ResultTypeConfig> getResultTypesByExtension(PackageConfig packageConfig);
|
||||
}
|
||||
+119
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.ResourceBundle;
|
||||
|
||||
import org.apache.struts2.convention.annotation.AnnotationTools;
|
||||
import org.apache.struts2.convention.annotation.ResultPath;
|
||||
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class is the implementation of the {@link ConventionsService}
|
||||
* interface and provides all of the defaults and annotation handling.
|
||||
* </p>
|
||||
*/
|
||||
public class ConventionsServiceImpl implements ConventionsService {
|
||||
private String resultPath;
|
||||
|
||||
/**
|
||||
* Constructs a new instance.
|
||||
*
|
||||
* @param resultPath The result path that is configured in the Struts configuration files using
|
||||
* the constant name of <strong>struts.convention.result.path</strong>.
|
||||
*/
|
||||
@Inject
|
||||
public ConventionsServiceImpl(@Inject("struts.convention.result.path") String resultPath) {
|
||||
this.resultPath = resultPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String determineResultPath(Class<?> actionClass) {
|
||||
String localResultPath = resultPath;
|
||||
ResultPath resultPathAnnotation = AnnotationTools.findAnnotation(actionClass, ResultPath.class);
|
||||
if (resultPathAnnotation != null) {
|
||||
if (resultPathAnnotation.value().equals("") && resultPathAnnotation.property().equals("")) {
|
||||
throw new ConfigurationException("The ResultPath annotation must have either" +
|
||||
" a value or property specified.");
|
||||
}
|
||||
|
||||
String property = resultPathAnnotation.property();
|
||||
if (property.equals("")) {
|
||||
localResultPath = resultPathAnnotation.value();
|
||||
} else {
|
||||
try {
|
||||
ResourceBundle strutsBundle = ResourceBundle.getBundle("struts");
|
||||
localResultPath = strutsBundle.getString(property);
|
||||
} catch (Exception e) {
|
||||
throw new ConfigurationException("The action class [" + actionClass + "] defines" +
|
||||
" a @ResultPath annotation and a property definition however the" +
|
||||
" struts.properties could not be found in the classpath using ResourceBundle" +
|
||||
" OR the bundle exists but the property [" + property + "] is not defined" +
|
||||
" in the file.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return localResultPath;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public String determineResultPath(ActionConfig actionConfig) {
|
||||
if (actionConfig == null) {
|
||||
return resultPath;
|
||||
}
|
||||
|
||||
try {
|
||||
return determineResultPath(Class.forName(actionConfig.getClassName()));
|
||||
} catch (ClassNotFoundException e) {
|
||||
throw new RuntimeException("Invalid action class configuration that references an unknown " +
|
||||
"class named [" + actionConfig.getClassName() + "]", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Map<String, ResultTypeConfig> getResultTypesByExtension(PackageConfig packageConfig) {
|
||||
Map<String, ResultTypeConfig> results = packageConfig.getAllResultTypeConfigs();
|
||||
|
||||
Map<String, ResultTypeConfig> resultsByExtension = new HashMap<String, ResultTypeConfig>();
|
||||
resultsByExtension.put("jsp", results.get("dispatcher"));
|
||||
resultsByExtension.put("vm", results.get("velocity"));
|
||||
resultsByExtension.put("ftl", results.get("freemarker"));
|
||||
// Issue 22 - Add html and htm as default result extensions
|
||||
resultsByExtension.put("html", results.get("dispatcher"));
|
||||
resultsByExtension.put("htm", results.get("dispatcher"));
|
||||
return resultsByExtension;
|
||||
}
|
||||
}
|
||||
+74
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class strips the word <b>Action</b> from the end of the class name
|
||||
* and possibly lowercases the name as well depending on the value of the
|
||||
* constant <strong>struts.convention.action.name.lowercase</strong>. If the
|
||||
* constant is set to <strong>true</strong>, this class will lowercase all
|
||||
* action names.
|
||||
* </p>
|
||||
*/
|
||||
public class DefaultActionNameBuilder implements ActionNameBuilder {
|
||||
private String actionSuffix = "Action";
|
||||
private boolean lowerCase;
|
||||
|
||||
@Inject
|
||||
public DefaultActionNameBuilder(@Inject(value="struts.convention.action.name.lowercase") String lowerCase) {
|
||||
this.lowerCase = Boolean.parseBoolean(lowerCase);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actionSuffix (Optional) Classes that end with these value will be mapped as actions
|
||||
* (defaults to "Action")
|
||||
*/
|
||||
@Inject(value = "struts.convention.action.suffix", required = false)
|
||||
public void setActionSuffix(String actionSuffix) {
|
||||
if (!StringTools.isTrimmedEmpty(actionSuffix)) {
|
||||
this.actionSuffix = actionSuffix;
|
||||
}
|
||||
}
|
||||
|
||||
public String build(String className) {
|
||||
String actionName = className;
|
||||
|
||||
// Truncate Action suffix if found
|
||||
if (actionName.endsWith(actionSuffix)) {
|
||||
actionName = actionName.substring(0, actionName.length() - actionSuffix.length());
|
||||
}
|
||||
|
||||
// Force initial letter of action to lowercase, if desired
|
||||
if ((lowerCase) && (actionName.length() > 1)) {
|
||||
int lowerPos = actionName.lastIndexOf('/') + 1;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append(actionName.substring(0, lowerPos));
|
||||
sb.append(Character.toLowerCase(actionName.charAt(lowerPos)));
|
||||
sb.append(actionName.substring(lowerPos + 1));
|
||||
actionName = sb.toString();
|
||||
}
|
||||
|
||||
return actionName;
|
||||
}
|
||||
}
|
||||
+109
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.AnnotationTools;
|
||||
import org.apache.struts2.convention.annotation.InterceptorRef;
|
||||
import org.apache.struts2.convention.annotation.InterceptorRefs;
|
||||
|
||||
import com.opensymphony.xwork2.ObjectFactory;
|
||||
import com.opensymphony.xwork2.config.Configuration;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
import com.opensymphony.xwork2.config.providers.InterceptorBuilder;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.AnnotationUtils;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* Builds interceptor mappings from annotations.
|
||||
* </p>
|
||||
*/
|
||||
public class DefaultInterceptorMapBuilder implements InterceptorMapBuilder {
|
||||
private static final Logger LOG = LoggerFactory
|
||||
.getLogger(DefaultInterceptorMapBuilder.class);
|
||||
|
||||
private Configuration configuration;
|
||||
|
||||
public List<InterceptorMapping> build(Class<?> actionClass, PackageConfig.Builder builder,
|
||||
String actionName, Action annotation) {
|
||||
List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(
|
||||
10);
|
||||
|
||||
//from @InterceptorRefs annotation
|
||||
InterceptorRefs interceptorRefs = AnnotationTools.findAnnotation(actionClass, InterceptorRefs.class);
|
||||
if (interceptorRefs != null)
|
||||
interceptorList.addAll(build(interceptorRefs.value(), actionName, builder));
|
||||
|
||||
//from @InterceptorRef annotation
|
||||
InterceptorRef interceptorRef = AnnotationTools.findAnnotation(actionClass, InterceptorRef.class);
|
||||
if (interceptorRef != null)
|
||||
interceptorList.addAll(build(new InterceptorRef[] {interceptorRef}, actionName, builder));
|
||||
|
||||
//from @Action annotation
|
||||
if (annotation != null) {
|
||||
InterceptorRef[] interceptors = annotation.interceptorRefs();
|
||||
if (interceptors != null) {
|
||||
interceptorList.addAll(build(interceptors, actionName, builder));
|
||||
}
|
||||
}
|
||||
|
||||
return interceptorList;
|
||||
}
|
||||
|
||||
protected List<InterceptorMapping> build(InterceptorRef[] interceptors, String actionName, PackageConfig.Builder builder) {
|
||||
List<InterceptorMapping> interceptorList = new ArrayList<InterceptorMapping>(
|
||||
10);
|
||||
for (InterceptorRef interceptor : interceptors) {
|
||||
if (LOG.isTraceEnabled())
|
||||
LOG.trace("Adding interceptor [#0] to [#1]",
|
||||
interceptor.value(), actionName);
|
||||
Map<String, String> params = StringTools.createParameterMap(interceptor
|
||||
.params());
|
||||
interceptorList.addAll(buildInterceptorList(builder,
|
||||
interceptor, params));
|
||||
}
|
||||
|
||||
return interceptorList;
|
||||
}
|
||||
|
||||
protected List<InterceptorMapping> buildInterceptorList(
|
||||
PackageConfig.Builder builder, InterceptorRef ref, Map params) {
|
||||
return InterceptorBuilder.constructInterceptorReference(builder, ref
|
||||
.value(), params, builder.build().getLocation(),
|
||||
(ObjectFactory) configuration.getContainer().getInstance(
|
||||
ObjectFactory.class));
|
||||
}
|
||||
|
||||
@Inject
|
||||
public void setConfiguration(Configuration configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
}
|
||||
+462
@@ -0,0 +1,462 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URL;
|
||||
import java.util.Arrays;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Result;
|
||||
import org.apache.struts2.convention.annotation.Results;
|
||||
|
||||
import com.opensymphony.xwork2.Action;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.finder.ResourceFinder;
|
||||
import com.opensymphony.xwork2.util.finder.Test;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class implements the ResultMapBuilder and traverses the web
|
||||
* application content directory looking for reasonably named JSPs and
|
||||
* other result types as well as annotations. This naming is in this
|
||||
* form:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* /resultPath/namespace/action-<result>.jsp
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* If there are any files in these locations than a result is created
|
||||
* for each one and the result names is the last portion of the file
|
||||
* name up to the . (dot).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* When results are found, new ResultConfig instances are created. The
|
||||
* result config that is created has a number of thing to be aware of:
|
||||
* </p>
|
||||
*
|
||||
* <ul>
|
||||
* <li>The result config contains the location parameter, which is
|
||||
* required by most result classes to figure out where to find the result.
|
||||
* In addition, the config has all the parameters from the default result-type
|
||||
* configuration.</li>
|
||||
* </ul>
|
||||
*
|
||||
* <p>
|
||||
* After loading the files in the web application, this class will then
|
||||
* use any annotations on the action class to override what was found in
|
||||
* the web application files. These annotations are the {@link Result}
|
||||
* and {@link Results} annotations. These two annotations allow an action
|
||||
* to supply different or non-forward based results for specific return
|
||||
* values of an action method.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The result path used by this class for locating JSPs and other
|
||||
* such result files can be set using the Struts2 constant named
|
||||
* <strong>struts.convention.result.path</strong> or using the
|
||||
* {@link org.apache.struts2.convention.annotation.ResultPath}
|
||||
* annotation.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This class will also locate and configure Results in the classpath,
|
||||
* including velocity and FreeMarker templates inside the classpath.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* All results that are conigured from resources are given a type corresponding
|
||||
* to the resources extension. The extensions and types are given in the
|
||||
* table below:
|
||||
* </p>
|
||||
*
|
||||
* <table>
|
||||
* <tr><th>Extension</th><th>Type</th></tr>
|
||||
* <tr><td>.jsp</td><td>dispatcher</td</tr>
|
||||
* <tr><td>.html</td><td>dispatcher</td</tr>
|
||||
* <tr><td>.htm</td><td>dispatcher</td</tr>
|
||||
* <tr><td>.vm</td><td>velocity</td</tr>
|
||||
* <tr><td>.ftl</td><td>freemarker</td</tr>
|
||||
* </table>
|
||||
*/
|
||||
public class DefaultResultMapBuilder implements ResultMapBuilder {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DefaultResultMapBuilder.class);
|
||||
private final ServletContext servletContext;
|
||||
private Set<String> relativeResultTypes;
|
||||
private ConventionsService conventionsService;
|
||||
private boolean flatResultLayout = true;
|
||||
|
||||
/**
|
||||
* Constructs the SimpleResultMapBuilder using the given result location.
|
||||
*
|
||||
* @param servletContext The ServletContext for finding the resources of the web application.
|
||||
* @param conventionsService The service used to assist in finding configuration and conventions.
|
||||
* @param relativeResultTypes The list of result types that can have locations that are relative
|
||||
* and the result location (which is the resultPath plus the namespace) prepended to them.
|
||||
*/
|
||||
@Inject
|
||||
public DefaultResultMapBuilder(ServletContext servletContext, ConventionsService conventionsService,
|
||||
@Inject("struts.convention.relative.result.types") String relativeResultTypes) {
|
||||
this.servletContext = servletContext;
|
||||
this.relativeResultTypes = new HashSet<String>(Arrays.asList(relativeResultTypes.split("\\s*[,]\\s*")));
|
||||
this.conventionsService = conventionsService;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param flatResultLayout If 'true' result resources will be expected to be in the form
|
||||
* ${namespace}/${actionName}-${result}.${extension}, otherwise in the form
|
||||
* ${namespace}/${actionName}/${result}.${extension}
|
||||
*/
|
||||
@Inject("struts.convention.result.flatLayout")
|
||||
public void setFlatResultLayout(String flatResultLayout) {
|
||||
this.flatResultLayout = "true".equals(flatResultLayout);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Map<String, ResultConfig> build(Class<?> actionClass,
|
||||
org.apache.struts2.convention.annotation.Action annotation, String actionName,
|
||||
PackageConfig packageConfig) {
|
||||
|
||||
// Get the default result location from the annotation or configuration
|
||||
String defaultResultPath = conventionsService.determineResultPath(actionClass);
|
||||
|
||||
// Add a slash
|
||||
if (!defaultResultPath.endsWith("/")) {
|
||||
defaultResultPath = defaultResultPath + "/";
|
||||
}
|
||||
|
||||
// Check for resources with the action name
|
||||
final String namespace = packageConfig.getNamespace();
|
||||
if (namespace != null && namespace.startsWith("/")) {
|
||||
defaultResultPath = defaultResultPath + namespace.substring(1);
|
||||
} else if (namespace != null) {
|
||||
defaultResultPath = defaultResultPath + namespace;
|
||||
}
|
||||
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Using final calculated namespace [#0]", namespace);
|
||||
}
|
||||
|
||||
// Add that ending slash for concatentation
|
||||
if (!defaultResultPath.endsWith("/")) {
|
||||
defaultResultPath += "/";
|
||||
}
|
||||
|
||||
String resultPrefix = defaultResultPath + actionName;
|
||||
|
||||
Map<String, ResultConfig> results = new HashMap<String, ResultConfig>();
|
||||
Map<String, ResultTypeConfig> resultsByExtension = conventionsService.getResultTypesByExtension(packageConfig);
|
||||
createFromResources(actionClass, results, defaultResultPath, resultPrefix, actionName,
|
||||
packageConfig, resultsByExtension);
|
||||
if (annotation != null && annotation.results() != null && annotation.results().length > 0) {
|
||||
createFromAnnotations(results, defaultResultPath, packageConfig, annotation.results(),
|
||||
actionClass, resultsByExtension);
|
||||
}
|
||||
|
||||
Results resultsAnn = actionClass.getAnnotation(Results.class);
|
||||
if (resultsAnn != null) {
|
||||
createFromAnnotations(results, defaultResultPath, packageConfig, resultsAnn.value(),
|
||||
actionClass, resultsByExtension);
|
||||
}
|
||||
|
||||
Result resultAnn = actionClass.getAnnotation(Result.class);
|
||||
if (resultAnn != null) {
|
||||
createFromAnnotations(results, defaultResultPath, packageConfig, new Result[]{resultAnn},
|
||||
actionClass, resultsByExtension);
|
||||
}
|
||||
|
||||
return results;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates any result types from the resources available in the web application. This scans the
|
||||
* web application resources using the servlet context.
|
||||
*
|
||||
* @param actionClass The action class the results are being built for.
|
||||
* @param results The results map to put the result configs created into.
|
||||
* @param resultPath The calculated path to the resources.
|
||||
* @param resultPrefix The prefix for the result. This is usually <code>/resultPath/actionName</code>.
|
||||
* @param actionName The action name which is used only for logging in this implementation.
|
||||
* @param packageConfig The package configuration which is passed along in order to determine
|
||||
* @param resultsByExtension The map of extensions to result type configuration instances.
|
||||
*/
|
||||
protected void createFromResources(Class<?> actionClass, Map<String, ResultConfig> results,
|
||||
final String resultPath, final String resultPrefix, final String actionName,
|
||||
PackageConfig packageConfig, Map<String, ResultTypeConfig> resultsByExtension) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Searching for results in the Servlet container at [#0]" +
|
||||
" with result prefix of [#1]", resultPath, resultPrefix);
|
||||
}
|
||||
|
||||
// Build from web application using the ServletContext
|
||||
@SuppressWarnings("unchecked")
|
||||
Set<String> paths = servletContext.getResourcePaths(flatResultLayout ? resultPath : resultPrefix);
|
||||
if (paths != null) {
|
||||
for (String path : paths) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Processing resource path [#0]", path);
|
||||
}
|
||||
|
||||
makeResults(actionClass, path, resultPrefix, results, packageConfig, resultsByExtension);
|
||||
}
|
||||
}
|
||||
|
||||
// Building from the classpath
|
||||
String classPathLocation = resultPath.startsWith("/") ?
|
||||
resultPath.substring(1, resultPath.length()) : resultPath;
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Searching for results in the class path at [#0]"
|
||||
+ " with a result prefix of [#1] and action name [#2]", classPathLocation, resultPrefix,
|
||||
actionName);
|
||||
}
|
||||
|
||||
ResourceFinder finder = new ResourceFinder(classPathLocation);
|
||||
try {
|
||||
Map<String, URL> matches = finder.getResourcesMap("");
|
||||
if (matches != null) {
|
||||
Test<URL> resourceTest = getResourceTest(resultPath, actionName);
|
||||
for (Map.Entry<String, URL> entry : matches.entrySet()) {
|
||||
if (resourceTest.test(entry.getValue())) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Processing URL [#0]", entry.getKey());
|
||||
}
|
||||
|
||||
String urlStr = entry.getValue().toString();
|
||||
int index = urlStr.lastIndexOf(resultPrefix);
|
||||
String path = urlStr.substring(index);
|
||||
makeResults(actionClass, path, resultPrefix, results, packageConfig, resultsByExtension);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
if (LOG.isErrorEnabled())
|
||||
LOG.error("Unable to scan directory [#0] for results", ex, classPathLocation);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private Test<URL> getResourceTest(final String resultPath, final String actionName) {
|
||||
return new Test<URL>() {
|
||||
public boolean test(URL url) {
|
||||
String urlStr = url.toString();
|
||||
int index = urlStr.lastIndexOf(resultPath);
|
||||
String path = urlStr.substring(index + resultPath.length());
|
||||
return path.startsWith(actionName);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes all the results for the given path.
|
||||
*
|
||||
* @param actionClass The action class the results are being built for.
|
||||
* @param path The path to build the result for.
|
||||
* @param resultPrefix The is the result prefix which is the result location plus the action name.
|
||||
* This is used to determine if the path contains a result code or not.
|
||||
* @param results The Map to place the result(s)
|
||||
* @param packageConfig The package config the results belong to.
|
||||
* @param resultsByExtension The map of extensions to result type configuration instances.
|
||||
*/
|
||||
protected void makeResults(Class<?> actionClass, String path, String resultPrefix,
|
||||
Map<String, ResultConfig> results, PackageConfig packageConfig,
|
||||
Map<String, ResultTypeConfig> resultsByExtension) {
|
||||
if (path.startsWith(resultPrefix)) {
|
||||
int indexOfDot = path.indexOf('.', resultPrefix.length());
|
||||
|
||||
// This case is when the path doesn't contain a result code
|
||||
if (indexOfDot == resultPrefix.length() || !flatResultLayout) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("The result file [#0] has no result code and therefore" +
|
||||
" will be associated with success, input and error by default. This might" +
|
||||
" be overridden by another result file or an annotation.", path);
|
||||
}
|
||||
|
||||
if (!results.containsKey(Action.SUCCESS)) {
|
||||
ResultConfig success = createResultConfig(actionClass,
|
||||
new ResultInfo(Action.SUCCESS, path, packageConfig, resultsByExtension),
|
||||
packageConfig, null);
|
||||
results.put(Action.SUCCESS, success);
|
||||
}
|
||||
if (!results.containsKey(Action.INPUT)) {
|
||||
ResultConfig input = createResultConfig(actionClass,
|
||||
new ResultInfo(Action.INPUT, path, packageConfig, resultsByExtension),
|
||||
packageConfig, null);
|
||||
results.put(Action.INPUT, input);
|
||||
}
|
||||
if (!results.containsKey(Action.ERROR)) {
|
||||
ResultConfig error = createResultConfig(actionClass,
|
||||
new ResultInfo(Action.ERROR, path, packageConfig, resultsByExtension),
|
||||
packageConfig, null);
|
||||
results.put(Action.ERROR, error);
|
||||
}
|
||||
|
||||
// This case is when the path contains a result code
|
||||
} else if (indexOfDot > resultPrefix.length()) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("The result file [#0] has a result code and therefore" +
|
||||
" will be associated with only that result code.", path);
|
||||
}
|
||||
|
||||
String resultCode = path.substring(resultPrefix.length() + 1, indexOfDot);
|
||||
ResultConfig result = createResultConfig(actionClass,
|
||||
new ResultInfo(resultCode, path, packageConfig, resultsByExtension),
|
||||
packageConfig, null);
|
||||
results.put(resultCode, result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected void createFromAnnotations(Map<String, ResultConfig> resultConfigs,
|
||||
String resultPath, PackageConfig packageConfig, Result[] results,
|
||||
Class<?> actionClass, Map<String, ResultTypeConfig> resultsByExtension) {
|
||||
// Check for multiple results on the class
|
||||
for (Result result : results) {
|
||||
ResultConfig config = createResultConfig(actionClass,
|
||||
new ResultInfo(result, packageConfig, resultPath, actionClass, resultsByExtension),
|
||||
packageConfig, result);
|
||||
if (config != null) {
|
||||
resultConfigs.put(config.getName(), config);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates the result configuration for the single result annotation. This will use all the
|
||||
* information from the annotation and anything that isn't specified will be fetched from the
|
||||
* PackageConfig defaults (if they exist).
|
||||
*
|
||||
* @param actionClass The action class the results are being built for.
|
||||
* @param info The result info that is used to create the ResultConfig instance.
|
||||
* @param packageConfig The PackageConfig to use to fetch defaults for result and parameters.
|
||||
* @param result (Optional) The result annotation to pull additional information from.
|
||||
* @return The ResultConfig or null if the Result annotation is given and the annotation is
|
||||
* targeted to some other action than this one.
|
||||
*/
|
||||
@SuppressWarnings(value = {"unchecked"})
|
||||
protected ResultConfig createResultConfig(Class<?> actionClass, ResultInfo info,
|
||||
PackageConfig packageConfig, Result result) {
|
||||
// Look up by the type that was determined from the annotation or by the extension in the
|
||||
// ResultInfo class
|
||||
ResultTypeConfig resultTypeConfig = packageConfig.getAllResultTypeConfigs().get(info.type);
|
||||
if (resultTypeConfig == null) {
|
||||
throw new ConfigurationException("The Result type [" + info.type + "] which is" +
|
||||
" defined in the Result annotation on the class [" + actionClass + "] or determined" +
|
||||
" by the file extension or is the default result type for the PackageConfig of the" +
|
||||
" action, could not be found as a result-type defined for the Struts/XWork package [" +
|
||||
packageConfig.getName() + "]");
|
||||
}
|
||||
|
||||
// Add the default parameters for the result type config (if any)
|
||||
HashMap<String, String> params = new HashMap<String, String>();
|
||||
if (resultTypeConfig.getParams() != null) {
|
||||
params.putAll(resultTypeConfig.getParams());
|
||||
}
|
||||
|
||||
// Handle the annotation
|
||||
if (result != null) {
|
||||
params.putAll(StringTools.createParameterMap(result.params()));
|
||||
}
|
||||
|
||||
// Map the location to the default param for the result or a param named location
|
||||
if (info.location != null) {
|
||||
String defaultParamName = resultTypeConfig.getDefaultResultParam();
|
||||
if (!params.containsKey(defaultParamName)) {
|
||||
params.put(defaultParamName, info.location);
|
||||
}
|
||||
} else if (LOG.isWarnEnabled()){
|
||||
LOG.warn("Result [#0] for action class [#1] is missing the location", info.name,
|
||||
actionClass.getSimpleName());
|
||||
}
|
||||
|
||||
return new ResultConfig.Builder(info.name, resultTypeConfig.getClassName()).addParams(params).build();
|
||||
}
|
||||
|
||||
class ResultInfo {
|
||||
public final String name;
|
||||
public final String location;
|
||||
public final String type;
|
||||
|
||||
public ResultInfo(String name, String location, PackageConfig packageConfig,
|
||||
Map<String, ResultTypeConfig> resultsByExtension) {
|
||||
this.name = name;
|
||||
this.location = location;
|
||||
this.type = determineType(location, packageConfig, resultsByExtension);
|
||||
}
|
||||
|
||||
public ResultInfo(Result result, PackageConfig packageConfig, String resultPath,
|
||||
Class<?> actionClass, Map<String, ResultTypeConfig> resultsByExtension) {
|
||||
this.name = result.name();
|
||||
if (!StringTools.isTrimmedEmpty(result.type())) {
|
||||
this.type = result.type();
|
||||
} else if (!StringTools.isTrimmedEmpty(result.location())) {
|
||||
this.type = determineType(result.location(), packageConfig, resultsByExtension);
|
||||
} else {
|
||||
throw new ConfigurationException("The action class [" + actionClass + "] contains a " +
|
||||
"result annotation that has no type parameter and no location parameter. One of " +
|
||||
"these must be defined.");
|
||||
}
|
||||
|
||||
// See if we can handle relative locations or not
|
||||
if (!StringTools.isTrimmedEmpty(result.location())) {
|
||||
if (relativeResultTypes.contains(this.type) && !result.location().startsWith("/")) {
|
||||
location = resultPath + result.location();
|
||||
} else {
|
||||
location = result.location();
|
||||
}
|
||||
} else {
|
||||
this.location = null;
|
||||
}
|
||||
}
|
||||
|
||||
String determineType(String location, PackageConfig packageConfig,
|
||||
Map<String, ResultTypeConfig> resultsByExtension) {
|
||||
int indexOfDot = location.lastIndexOf(".");
|
||||
if (indexOfDot > 0) {
|
||||
String extension = location.substring(indexOfDot + 1);
|
||||
ResultTypeConfig resultTypeConfig = resultsByExtension.get(extension);
|
||||
if (resultTypeConfig != null) {
|
||||
return resultTypeConfig.getName();
|
||||
} else
|
||||
throw new ConfigurationException("Unable to find a result type for extension [" + extension + "] " +
|
||||
"in location attribute [" + location + "].");
|
||||
} else {
|
||||
return packageConfig.getFullDefaultResultType();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
|
||||
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface defines how interceptors are built from
|
||||
* annotations.
|
||||
* </p>
|
||||
*/
|
||||
public interface InterceptorMapBuilder {
|
||||
/**
|
||||
* Builds the interceptor configurations given the action information.
|
||||
*
|
||||
* @param actionClass The class of the action.
|
||||
* @param annotation The action annotation.
|
||||
* @param actionName The action name.
|
||||
* @param builder The package configuration builder.
|
||||
* @return The mapping of the interceptors. If there were none found
|
||||
* then this should return an empty List.
|
||||
*/
|
||||
List<InterceptorMapping> build(Class<?> actionClass, PackageConfig.Builder builder, String actionName, Action annotation);
|
||||
}
|
||||
+797
@@ -0,0 +1,797 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Modifier;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.Actions;
|
||||
import org.apache.struts2.convention.annotation.AnnotationTools;
|
||||
import org.apache.struts2.convention.annotation.DefaultInterceptorRef;
|
||||
import org.apache.struts2.convention.annotation.ExceptionMapping;
|
||||
import org.apache.struts2.convention.annotation.ExceptionMappings;
|
||||
import org.apache.struts2.convention.annotation.Namespace;
|
||||
import org.apache.struts2.convention.annotation.Namespaces;
|
||||
import org.apache.struts2.convention.annotation.ParentPackage;
|
||||
|
||||
import com.opensymphony.xwork2.ObjectFactory;
|
||||
import com.opensymphony.xwork2.config.Configuration;
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig;
|
||||
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultConfig;
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.finder.ClassFinder;
|
||||
import com.opensymphony.xwork2.util.finder.Test;
|
||||
import com.opensymphony.xwork2.util.finder.UrlSet;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class implements the ActionConfigBuilder interface.
|
||||
* </p>
|
||||
*/
|
||||
public class PackageBasedActionConfigBuilder implements ActionConfigBuilder {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(PackageBasedActionConfigBuilder.class);
|
||||
private final Configuration configuration;
|
||||
private final ActionNameBuilder actionNameBuilder;
|
||||
private final ResultMapBuilder resultMapBuilder;
|
||||
private final InterceptorMapBuilder interceptorMapBuilder;
|
||||
private final ObjectFactory objectFactory;
|
||||
private final String defaultParentPackage;
|
||||
private final boolean redirectToSlash;
|
||||
private String[] actionPackages;
|
||||
private String[] excludePackages;
|
||||
private String[] packageLocators;
|
||||
private String[] excludeJars;
|
||||
private String packageLocatorsBasePackage;
|
||||
private boolean disableJarScanning = true;
|
||||
private boolean disableActionScanning = false;
|
||||
private boolean disablePackageLocatorsScanning = false;
|
||||
private String actionSuffix = "Action";
|
||||
private boolean checkImplementsAction = true;
|
||||
private boolean mapAllMatches = false;
|
||||
|
||||
/**
|
||||
* Constructs actions based on a list of packages.
|
||||
*
|
||||
* @param configuration The XWork configuration that the new package configs and action configs
|
||||
* are added to.
|
||||
* @param actionNameBuilder The action name builder used to convert action class names to action
|
||||
* names.
|
||||
* @param resultMapBuilder The result map builder used to create ResultConfig mappings for each
|
||||
* action.
|
||||
* @param interceptorMapBuilder The interceptor map builder used to create InterceptorConfig mappings for each
|
||||
* action.
|
||||
* @param objectFactory The ObjectFactory used to create the actions and such.
|
||||
* @param redirectToSlash A boolean parameter that controls whether or not this will create an
|
||||
* action for indexes. If this is set to true, index actions are not created because
|
||||
* the unknown handler will redirect from /foo to /foo/. The only action that is created
|
||||
* is to the empty action in the namespace (e.g. the namespace /foo and the action "").
|
||||
* @param defaultParentPackage The default parent package for all the configuration.
|
||||
*/
|
||||
@Inject
|
||||
public PackageBasedActionConfigBuilder(Configuration configuration, ActionNameBuilder actionNameBuilder,
|
||||
ResultMapBuilder resultMapBuilder, InterceptorMapBuilder interceptorMapBuilder, ObjectFactory objectFactory,
|
||||
@Inject("struts.convention.redirect.to.slash") String redirectToSlash,
|
||||
@Inject("struts.convention.default.parent.package") String defaultParentPackage) {
|
||||
|
||||
// Validate that the parameters are okay
|
||||
this.configuration = configuration;
|
||||
this.actionNameBuilder = actionNameBuilder;
|
||||
this.resultMapBuilder = resultMapBuilder;
|
||||
this.interceptorMapBuilder = interceptorMapBuilder;
|
||||
this.objectFactory = objectFactory;
|
||||
this.redirectToSlash = Boolean.parseBoolean(redirectToSlash);
|
||||
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Setting action default parent package to [#0]", defaultParentPackage);
|
||||
}
|
||||
|
||||
this.defaultParentPackage = defaultParentPackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param disableActionScanning Disable scanning for actions
|
||||
*/
|
||||
@Inject(value = "struts.convention.action.disableScanning", required = false)
|
||||
public void setDisableActionScanning(String disableActionScanning) {
|
||||
this.disableActionScanning = "true".equals(disableActionScanning);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param exlcudeJars Comma separated list of regular expressions of jars to be exluded.
|
||||
* Ignored if "struts.convention.action.disableJarScanning" is true
|
||||
*/
|
||||
@Inject(value = "struts.convention.action.excludeJars", required = false)
|
||||
public void setExcludeJars(String excludeJars) {
|
||||
this.excludeJars = excludeJars.split("\\s*[,]\\s*");;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param disableJarScanning Disable scanning jar files for actions
|
||||
*/
|
||||
@Inject(value = "struts.convention.action.disableJarScanning", required = false)
|
||||
public void setDisableJarScanning(String disableJarScanning) {
|
||||
this.disableJarScanning = "true".equals(disableJarScanning);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param disableActionScanning If set to true, only the named packages will be scanned
|
||||
*/
|
||||
@Inject(value = "struts.convention.package.locators.disable", required = false)
|
||||
public void setDisablePackageLocatorsScanning(String disablePackageLocatorsScanning) {
|
||||
this.disablePackageLocatorsScanning = "true".equals(disablePackageLocatorsScanning);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actionPackages (Optional) An optional list of action packages that this should create
|
||||
* configuration for.
|
||||
*/
|
||||
@Inject(value = "struts.convention.action.packages", required = false)
|
||||
public void setActionPackages(String actionPackages) {
|
||||
if (!StringTools.isTrimmedEmpty(actionPackages)) {
|
||||
this.actionPackages = actionPackages.split("\\s*[,]\\s*");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actionPackages (Optional) Map classes that implement com.opensymphony.xwork2.Action
|
||||
* as actions
|
||||
*/
|
||||
@Inject(value = "struts.convention.action.checkImplementsAction", required = false)
|
||||
public void setCheckImplementsAction(String checkImplementsAction) {
|
||||
this.checkImplementsAction = "true".equals(checkImplementsAction);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actionSuffix (Optional) Classes that end with these value will be mapped as actions
|
||||
* (defaults to "Action")
|
||||
*/
|
||||
@Inject(value = "struts.convention.action.suffix", required = false)
|
||||
public void setActionSuffix(String actionSuffix) {
|
||||
if (!StringTools.isTrimmedEmpty(actionSuffix)) {
|
||||
this.actionSuffix = actionSuffix;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param excludePackages (Optional) A list of packages that should be skipped when building
|
||||
* configuration.
|
||||
*/
|
||||
@Inject(value = "struts.convention.exclude.packages", required = false)
|
||||
public void setExcludePackages(String excludePackages) {
|
||||
if (!StringTools.isTrimmedEmpty(excludePackages)) {
|
||||
this.excludePackages = excludePackages.split("\\s*[,]\\s*");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param packageLocators (Optional) A list of names used to find action packages.
|
||||
*/
|
||||
@Inject(value = "struts.convention.package.locators", required = false)
|
||||
public void setPackageLocators(String packageLocators) {
|
||||
this.packageLocators = packageLocators.split("\\s*[,]\\s*");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param packageLocatorsBasePackage (Optional) If set, only packages that start with this
|
||||
* name will be scanned for actions.
|
||||
*/
|
||||
@Inject(value = "struts.convention.package.locators.basePackage", required = false)
|
||||
public void setPackageLocatorsBase(String packageLocatorsBasePackage) {
|
||||
this.packageLocatorsBasePackage = packageLocatorsBasePackage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param mapAllMatches (Optional) Map actions that match the "*${Suffix}" pattern
|
||||
* even if they don't have a default method. The mapping from
|
||||
* the url to the action will be delegated the action mapper.
|
||||
*/
|
||||
@Inject(value = "struts.convention.action.mapAllMatches", required = false)
|
||||
public void setMapAllMatches(String mapAllMatches) {
|
||||
this.mapAllMatches = "true".equals(mapAllMatches);
|
||||
}
|
||||
|
||||
/**
|
||||
* Builds the action configurations by loading all classes in the packages specified by the
|
||||
* property <b>struts.convention.action.packages</b> and then figuring out which classes implement Action
|
||||
* or have Action in their name. Next, if this class is in a Java package that hasn't been
|
||||
* inspected a new PackageConfig (XWork) is created for that Java package using the Java package
|
||||
* name. This will contain all the ActionConfigs for all the Action classes that are discovered
|
||||
* within that Java package. Next, each class is inspected for the {@link ParentPackage}
|
||||
* annotation which is used to control the parent package for a specific action. Lastly, the
|
||||
* {@link ResultMapBuilder} is used to create ResultConfig instances of the action.
|
||||
*/
|
||||
public void buildActionConfigs() {
|
||||
if (!disableActionScanning ) {
|
||||
if (actionPackages == null && packageLocators == null) {
|
||||
throw new ConfigurationException("At least a list of action packages or action package locators " +
|
||||
"must be given using one of the properties [struts.convention.action.packages] or " +
|
||||
"[struts.convention.package.locators]");
|
||||
}
|
||||
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Loading action configurations");
|
||||
if (actionPackages != null) {
|
||||
LOG.trace("Actions being loaded from action packages " + Arrays.asList(actionPackages));
|
||||
}
|
||||
if (packageLocators != null) {
|
||||
LOG.trace("Actions being loaded using package locators " + Arrays.asList(packageLocators));
|
||||
}
|
||||
if (excludePackages != null) {
|
||||
LOG.trace("Excluding actions from packages " + Arrays.asList(excludePackages));
|
||||
}
|
||||
}
|
||||
|
||||
Set<Class> classes = findActions();
|
||||
buildConfiguration(classes);
|
||||
}
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected Set<Class> findActions() {
|
||||
Set<Class> classes = new HashSet<Class>();
|
||||
try {
|
||||
if (actionPackages != null || (packageLocators != null && !disablePackageLocatorsScanning)) {
|
||||
ClassFinder finder = new ClassFinder(getClassLoader(), buildUrlSet().getUrls(), true);
|
||||
|
||||
// named packages
|
||||
if (actionPackages != null) {
|
||||
for (String packageName : actionPackages) {
|
||||
Test<ClassFinder.ClassInfo> test = getPackageFinderTest(packageName);
|
||||
classes.addAll(finder.findClasses(test));
|
||||
}
|
||||
}
|
||||
|
||||
//package locators
|
||||
if (packageLocators != null && !disablePackageLocatorsScanning) {
|
||||
for (String packageLocator : packageLocators) {
|
||||
Test<ClassFinder.ClassInfo> test = getPackageLocatorTest(packageLocator);
|
||||
classes.addAll(finder.findClasses(test));
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
if (LOG.isErrorEnabled())
|
||||
LOG.error("Unable to scan named packages", ex);
|
||||
}
|
||||
|
||||
return classes;
|
||||
}
|
||||
|
||||
private UrlSet buildUrlSet() throws IOException {
|
||||
UrlSet urlSet = new UrlSet(getClassLoader());
|
||||
|
||||
urlSet = urlSet.exclude(ClassLoader.getSystemClassLoader().getParent());
|
||||
urlSet = urlSet.excludeJavaExtDirs();
|
||||
urlSet = urlSet.excludeJavaEndorsedDirs();
|
||||
urlSet = urlSet.excludeJavaHome();
|
||||
urlSet = urlSet.excludePaths(System.getProperty("sun.boot.class.path", ""));
|
||||
urlSet = urlSet.exclude(".*/JavaVM.framework/.*");
|
||||
|
||||
if (disableJarScanning) {
|
||||
urlSet = urlSet.exclude(".*?jar(!/)?");
|
||||
} else if (excludeJars != null) {
|
||||
for (String pattern : excludeJars) {
|
||||
urlSet = urlSet.exclude(pattern.trim());
|
||||
}
|
||||
}
|
||||
|
||||
return urlSet;
|
||||
}
|
||||
|
||||
private ClassLoader getClassLoader() {
|
||||
return Thread.currentThread().getContextClassLoader();
|
||||
}
|
||||
|
||||
protected Test<ClassFinder.ClassInfo> getPackageFinderTest(final String packageName) {
|
||||
// so "my.package" does not match "my.package2.test"
|
||||
final String strictPackageName = packageName + ".";
|
||||
return new Test<ClassFinder.ClassInfo>() {
|
||||
public boolean test(ClassFinder.ClassInfo classInfo) {
|
||||
String classPackageName = classInfo.getPackageName();
|
||||
boolean inPackage = classPackageName.equals(packageName) || classPackageName.startsWith(strictPackageName);
|
||||
boolean nameMatches = classInfo.getName().endsWith(actionSuffix);
|
||||
|
||||
try {
|
||||
return inPackage && (nameMatches || (checkImplementsAction && com.opensymphony.xwork2.Action.class.isAssignableFrom(classInfo.get())));
|
||||
} catch (ClassNotFoundException ex) {
|
||||
if (LOG.isErrorEnabled())
|
||||
LOG.error("Unable to load class [#0]", ex, classInfo.getName());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected Test<ClassFinder.ClassInfo> getPackageLocatorTest(final String packageLocator) {
|
||||
return new Test<ClassFinder.ClassInfo>() {
|
||||
public boolean test(ClassFinder.ClassInfo classInfo) {
|
||||
String packageName = classInfo.getPackageName();
|
||||
if (packageName.length() > 0 && (packageLocatorsBasePackage == null || packageName.startsWith(packageLocatorsBasePackage))) {
|
||||
String[] splitted = packageName.split("\\.");
|
||||
|
||||
boolean packageMatches = StringTools.contains(splitted, packageLocator, false);
|
||||
boolean nameMatches = classInfo.getName().endsWith(actionSuffix);
|
||||
|
||||
try {
|
||||
return packageMatches && (nameMatches || (checkImplementsAction && com.opensymphony.xwork2.Action.class.isAssignableFrom(classInfo.get())));
|
||||
} catch (ClassNotFoundException ex) {
|
||||
if (LOG.isErrorEnabled())
|
||||
LOG.error("Unable to load class [#0]", ex, classInfo.getName());
|
||||
return false;
|
||||
}
|
||||
} else
|
||||
return false;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void buildConfiguration(Set<Class> classes) {
|
||||
Map<String, PackageConfig.Builder> packageConfigs = new HashMap<String, PackageConfig.Builder>();
|
||||
|
||||
for (Class<?> actionClass : classes) {
|
||||
// Skip all interfaces, enums, annotations, and abstract classes
|
||||
if (actionClass.isAnnotation() || actionClass.isInterface() || actionClass.isEnum() ||
|
||||
(actionClass.getModifiers() & Modifier.ABSTRACT) != 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Tell the ObjectFactory about this class
|
||||
try {
|
||||
objectFactory.getClassInstance(actionClass.getName());
|
||||
} catch (ClassNotFoundException e) {
|
||||
// Impossible
|
||||
new Throwable().printStackTrace();
|
||||
System.exit(1);
|
||||
}
|
||||
|
||||
// Determine the action package
|
||||
String actionPackage = actionClass.getPackage().getName();
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Processing class [#0] in package [#1]", actionClass.getName(), actionPackage);
|
||||
}
|
||||
|
||||
// Determine the default namespace and action name
|
||||
List<String> namespaces = determineActionNamespace(actionClass);
|
||||
for (String namespace : namespaces) {
|
||||
String defaultActionName = determineActionName(actionClass);
|
||||
String defaultActionMethod = "execute";
|
||||
PackageConfig.Builder defaultPackageConfig = getPackageConfig(packageConfigs, namespace,
|
||||
actionPackage, actionClass, null);
|
||||
|
||||
// Verify that the annotations have no errors and also determine if the default action
|
||||
// configuration should still be built or not.
|
||||
Map<String, List<Action>> map = getActionAnnotations(actionClass);
|
||||
Set<String> actionNames = new HashSet<String>();
|
||||
if (!map.containsKey(defaultActionMethod) && ReflectionTools.containsMethod(actionClass, defaultActionMethod)) {
|
||||
boolean found = false;
|
||||
for (String method : map.keySet()) {
|
||||
List<Action> actions = map.get(method);
|
||||
for (Action action : actions) {
|
||||
|
||||
// Check if there are duplicate action names in the annotations.
|
||||
String actionName = action.value().equals(Action.DEFAULT_VALUE) ? defaultActionName : action.value();
|
||||
if (actionNames.contains(actionName)) {
|
||||
throw new ConfigurationException("The action class [" + actionClass +
|
||||
"] contains two methods with an action name annotation whose value " +
|
||||
"is the same (they both might be empty as well).");
|
||||
} else {
|
||||
actionNames.add(actionName);
|
||||
}
|
||||
|
||||
// Check this annotation is the default action
|
||||
if (action.value().equals(Action.DEFAULT_VALUE)) {
|
||||
found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Build the default
|
||||
if (!found) {
|
||||
createActionConfig(defaultPackageConfig, actionClass, defaultActionName, defaultActionMethod, null);
|
||||
}
|
||||
}
|
||||
|
||||
// Build the actions for the annotations
|
||||
for (String method : map.keySet()) {
|
||||
List<Action> actions = map.get(method);
|
||||
for (Action action : actions) {
|
||||
PackageConfig.Builder pkgCfg = defaultPackageConfig;
|
||||
if (action.value().contains("/")) {
|
||||
pkgCfg = getPackageConfig(packageConfigs, namespace, actionPackage,
|
||||
actionClass, action);
|
||||
}
|
||||
|
||||
createActionConfig(pkgCfg, actionClass, defaultActionName, method, action);
|
||||
}
|
||||
}
|
||||
|
||||
// some actions will not have any @Action or a default method, like the rest actions
|
||||
// where the action mapper is the one that finds the right method at runtime
|
||||
if (map.isEmpty() && mapAllMatches) {
|
||||
Action actionAnnotation = actionClass.getAnnotation(Action.class);
|
||||
createActionConfig(defaultPackageConfig, actionClass, defaultActionName, null, actionAnnotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
buildIndexActions(packageConfigs);
|
||||
|
||||
// Add the new actions to the configuration
|
||||
Set<String> packageNames = packageConfigs.keySet();
|
||||
for (String packageName : packageNames) {
|
||||
configuration.addPackageConfig(packageName, packageConfigs.get(packageName).build());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the namespace(s) for the action based on the action class. If there is a {@link Namespace}
|
||||
* annotation on the class (including parent classes) or on the package that the class is in, than
|
||||
* it is used. Otherwise, the Java package name that the class is in is used in conjunction with
|
||||
* either the <b>struts.convention.action.packages</b> or <b>struts.convention.package.locators</b>
|
||||
* configuration values. These are used to determine which part of the Java package name should
|
||||
* be converted into the namespace for the XWork PackageConfig.
|
||||
*
|
||||
* @param actionClass The action class.
|
||||
* @return The namespace or an empty string.
|
||||
*/
|
||||
protected List<String> determineActionNamespace(Class<?> actionClass) {
|
||||
List<String> namespaces = new ArrayList<String>();
|
||||
|
||||
// Check if there is a class or package level annotation for the namespace
|
||||
//single namespace
|
||||
Namespace namespaceAnnotation = AnnotationTools.findAnnotation(actionClass, Namespace.class);
|
||||
if (namespaceAnnotation != null) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Using non-default action namespace from Namespace annotation of [#0]", namespaceAnnotation.value());
|
||||
}
|
||||
|
||||
namespaces.add(namespaceAnnotation.value());
|
||||
}
|
||||
|
||||
//multiple annotations
|
||||
Namespaces namespacesAnnotation = AnnotationTools.findAnnotation(actionClass, Namespaces.class);
|
||||
if (namespacesAnnotation != null) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (Namespace namespace : namespacesAnnotation.value())
|
||||
sb.append(namespace.value()).append(",");
|
||||
sb.deleteCharAt(sb.length() - 1);
|
||||
LOG.trace("Using non-default action namespaces from Namespaces annotation of [#0]", sb.toString());
|
||||
}
|
||||
|
||||
for (Namespace namespace : namespacesAnnotation.value())
|
||||
namespaces.add(namespace.value());
|
||||
}
|
||||
|
||||
//don't use default if there are annotations
|
||||
if (!namespaces.isEmpty())
|
||||
return namespaces;
|
||||
|
||||
String pkg = actionClass.getPackage().getName();
|
||||
String pkgPart = null;
|
||||
if (actionPackages != null) {
|
||||
for (String actionPackage : actionPackages) {
|
||||
if (pkg.startsWith(actionPackage)) {
|
||||
pkgPart = actionClass.getName().substring(actionPackage.length() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pkgPart == null && packageLocators != null) {
|
||||
for (String packageLocator : packageLocators) {
|
||||
int index = pkg.lastIndexOf(packageLocator);
|
||||
|
||||
// This ensures that the match is at the end, beginning or has a dot on each side of it
|
||||
if (index >= 0 && (index + packageLocator.length() == pkg.length() || index == 0 ||
|
||||
(pkg.charAt(index - 1) == '.' && pkg.charAt(index + packageLocator.length()) == '.'))) {
|
||||
pkgPart = actionClass.getName().substring(index + packageLocator.length() + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pkgPart != null) {
|
||||
final int indexOfDot = pkgPart.lastIndexOf('.');
|
||||
if (indexOfDot >= 0) {
|
||||
String convertedNamespace = actionNameBuilder.build(pkgPart.substring(0, indexOfDot));
|
||||
namespaces.add("/" + convertedNamespace.replace('.', '/'));
|
||||
return namespaces;
|
||||
}
|
||||
}
|
||||
|
||||
namespaces.add("");
|
||||
return namespaces;
|
||||
}
|
||||
|
||||
/**
|
||||
* Converts the class name into an action name using the ActionNameBuilder.
|
||||
*
|
||||
* @param actionClass The action class.
|
||||
* @return The action name.
|
||||
*/
|
||||
protected String determineActionName(Class<?> actionClass) {
|
||||
String actionName = actionNameBuilder.build(actionClass.getSimpleName());
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Got actionName for class [#0] of [#1]", actionClass.toString(), actionName);
|
||||
}
|
||||
|
||||
return actionName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Locates all of the {@link Actions} and {@link Action} annotations on methods within the Action
|
||||
* class and its parent classes.
|
||||
*
|
||||
* @param actionClass The action class.
|
||||
* @return The list of annotations or an empty list if there are none.
|
||||
*/
|
||||
protected Map<String, List<Action>> getActionAnnotations(Class<?> actionClass) {
|
||||
Method[] methods = actionClass.getMethods();
|
||||
Map<String, List<Action>> map = new HashMap<String, List<Action>>();
|
||||
for (Method method : methods) {
|
||||
Actions actionsAnnotation = method.getAnnotation(Actions.class);
|
||||
if (actionsAnnotation != null) {
|
||||
Action[] actionArray = actionsAnnotation.value();
|
||||
boolean valuelessSeen = false;
|
||||
List<Action> actions = new ArrayList<Action>();
|
||||
for (Action ann : actionArray) {
|
||||
if (ann.value().equals(Action.DEFAULT_VALUE) && !valuelessSeen) {
|
||||
valuelessSeen = true;
|
||||
} else if (ann.value().equals(Action.DEFAULT_VALUE)) {
|
||||
throw new ConfigurationException("You may only add a single Action " +
|
||||
"annotation that has no value parameter.");
|
||||
}
|
||||
|
||||
actions.add(ann);
|
||||
}
|
||||
|
||||
map.put(method.getName(), actions);
|
||||
} else {
|
||||
Action ann = method.getAnnotation(Action.class);
|
||||
if (ann != null) {
|
||||
map.put(method.getName(), Arrays.asList(ann));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a single ActionConfig object.
|
||||
*
|
||||
* @param pkgCfg The package the action configuration instance will belong to.
|
||||
* @param actionClass The action class.
|
||||
* @param actionName The name of the action.
|
||||
* @param actionMethod The method that the annotation was on (if the annotation is not null) or
|
||||
* the default method (execute).
|
||||
* @param annotation The ActionName annotation that might override the action name and possibly
|
||||
*/
|
||||
protected void createActionConfig(PackageConfig.Builder pkgCfg, Class<?> actionClass, String actionName,
|
||||
String actionMethod, Action annotation) {
|
||||
if (annotation != null) {
|
||||
actionName = annotation.value() != null && annotation.value().equals(Action.DEFAULT_VALUE) ?
|
||||
actionName : annotation.value();
|
||||
actionName = StringTools.lastToken(actionName, "/");
|
||||
}
|
||||
|
||||
ActionConfig.Builder actionConfig = new ActionConfig.Builder(pkgCfg.getName(),
|
||||
actionName, actionClass.getName());
|
||||
actionConfig.methodName(actionMethod);
|
||||
|
||||
if (LOG.isDebugEnabled()) {
|
||||
LOG.debug("Creating action config for class [#0], name [#1] and package name [#2] in namespace [#3]",
|
||||
actionClass.toString(), actionName, pkgCfg.getName(), pkgCfg.getNamespace());
|
||||
}
|
||||
|
||||
//build interceptors
|
||||
List<InterceptorMapping> interceptors = interceptorMapBuilder.build(actionClass, pkgCfg, actionName, annotation);
|
||||
actionConfig.addInterceptors(interceptors);
|
||||
|
||||
//build results
|
||||
Map<String, ResultConfig> results = resultMapBuilder.build(actionClass, annotation, actionName, pkgCfg.build());
|
||||
actionConfig.addResultConfigs(results);
|
||||
|
||||
//add params
|
||||
if (annotation != null)
|
||||
actionConfig.addParams(StringTools.createParameterMap(annotation.params()));
|
||||
|
||||
//add exception mappings from annotation
|
||||
if (annotation != null && annotation.exceptionMappings() != null)
|
||||
actionConfig.addExceptionMappings(buildExceptionMappings(annotation.exceptionMappings(), actionName));
|
||||
|
||||
//add exception mapping from class
|
||||
ExceptionMappings exceptionMappings = actionClass.getAnnotation(ExceptionMappings.class);
|
||||
if (exceptionMappings != null)
|
||||
actionConfig.addExceptionMappings(buildExceptionMappings(exceptionMappings.value(), actionName));
|
||||
|
||||
//add
|
||||
pkgCfg.addActionConfig(actionName, actionConfig.build());
|
||||
|
||||
//check if an action with the same name exists on that package (from XML config probably)
|
||||
PackageConfig existingPkg = configuration.getPackageConfig(pkgCfg.getName());
|
||||
if (existingPkg != null) {
|
||||
// there is a package already with that name, check action
|
||||
ActionConfig existingActionConfig = existingPkg.getActionConfigs().get(actionName);
|
||||
if (existingActionConfig != null && LOG.isWarnEnabled())
|
||||
LOG.warn("Duplicated action definition in package [#0] with name [#1]. First definition was loaded from [#3]", pkgCfg.getName(), actionName, existingActionConfig.getLocation().toString());
|
||||
}
|
||||
}
|
||||
|
||||
private List<ExceptionMappingConfig> buildExceptionMappings(ExceptionMapping[] exceptions, String actionName) {
|
||||
List<ExceptionMappingConfig> exceptionMappings = new ArrayList<ExceptionMappingConfig>();
|
||||
|
||||
for (ExceptionMapping exceptionMapping : exceptions) {
|
||||
if (LOG.isTraceEnabled())
|
||||
LOG.trace("Mapping exception [#0] to result [#1] for action [#2]", exceptionMapping.exception(),
|
||||
exceptionMapping.result(), actionName);
|
||||
ExceptionMappingConfig.Builder builder = new ExceptionMappingConfig.Builder(null, exceptionMapping
|
||||
.exception(), exceptionMapping.result());
|
||||
if (exceptionMapping.params() != null)
|
||||
builder.addParams(StringTools.createParameterMap(exceptionMapping.params()));
|
||||
exceptionMappings.add(builder.build());
|
||||
}
|
||||
|
||||
return exceptionMappings;
|
||||
}
|
||||
|
||||
private PackageConfig.Builder getPackageConfig(final Map<String, PackageConfig.Builder> packageConfigs,
|
||||
String actionNamespace, final String actionPackage, final Class<?> actionClass,
|
||||
Action action) {
|
||||
if (action != null && !action.value().equals(Action.DEFAULT_VALUE)) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Using non-default action namespace from the Action annotation of [#0]", action.value());
|
||||
}
|
||||
actionNamespace = StringTools.upToLastToken(action.value(), "/");
|
||||
}
|
||||
|
||||
// Next grab the parent annotation from the class
|
||||
ParentPackage parent = AnnotationTools.findAnnotation(actionClass, ParentPackage.class);
|
||||
String parentName = null;
|
||||
if (parent != null) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Using non-default parent package from annotation of [#0]", parent.value());
|
||||
}
|
||||
|
||||
parentName = parent.value();
|
||||
}
|
||||
|
||||
// Finally use the default
|
||||
if (parentName == null) {
|
||||
parentName = defaultParentPackage;
|
||||
}
|
||||
|
||||
if (parentName == null) {
|
||||
throw new ConfigurationException("Unable to determine the parent XWork package for the action class [" +
|
||||
actionClass.getName() + "]");
|
||||
}
|
||||
|
||||
PackageConfig parentPkg = configuration.getPackageConfig(parentName);
|
||||
if (parentPkg == null) {
|
||||
throw new ConfigurationException("Unable to locate parent package [" + parentName + "]");
|
||||
}
|
||||
|
||||
// Grab based on package-namespace and if it exists, we need to ensure the existing one has
|
||||
// the correct parent package. If not, we need to create a new package config
|
||||
String name = actionPackage + "#" + parentPkg.getName() + "#" + actionNamespace;
|
||||
PackageConfig.Builder pkgConfig = packageConfigs.get(name);
|
||||
if (pkgConfig == null) {
|
||||
pkgConfig = new PackageConfig.Builder(name).namespace(actionNamespace).addParent(parentPkg);
|
||||
packageConfigs.put(name, pkgConfig);
|
||||
|
||||
//check for @DefaultInterceptorRef in the package
|
||||
DefaultInterceptorRef defaultInterceptorRef = AnnotationTools.findAnnotation(actionClass, DefaultInterceptorRef.class);
|
||||
if (defaultInterceptorRef != null) {
|
||||
pkgConfig.defaultInterceptorRef(defaultInterceptorRef.value());
|
||||
|
||||
if (LOG.isTraceEnabled())
|
||||
LOG.trace("Setting [#0] as the default interceptor ref for [#1]", defaultInterceptorRef.value(), pkgConfig.getName());
|
||||
}
|
||||
}
|
||||
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Created package config named [#0] with a namespace [#1]", name, actionNamespace);
|
||||
}
|
||||
|
||||
return pkgConfig;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine all the index handling actions and results based on this logic:
|
||||
*
|
||||
* 1. Loop over all the namespaces such as /foo and see if it has an action named index
|
||||
* 2. If an action doesn't exists in the parent namespace of the same name, create an action
|
||||
* in the parent namespace of the same name as the namespace that points to the index
|
||||
* action in the namespace. e.g. /foo -> /foo/index
|
||||
* 3. Create the action in the namespace for empty string if it doesn't exist. e.g. /foo/
|
||||
* the action is "" and the namespace is /foo
|
||||
*
|
||||
* @param packageConfigs Used to store the actions.
|
||||
*/
|
||||
protected void buildIndexActions(Map<String, PackageConfig.Builder> packageConfigs) {
|
||||
Map<String, PackageConfig.Builder> byNamespace = new HashMap<String, PackageConfig.Builder>();
|
||||
Collection<PackageConfig.Builder> values = packageConfigs.values();
|
||||
for (PackageConfig.Builder packageConfig : values) {
|
||||
byNamespace.put(packageConfig.getNamespace(), packageConfig);
|
||||
}
|
||||
|
||||
// Step #1
|
||||
Set<String> namespaces = byNamespace.keySet();
|
||||
for (String namespace : namespaces) {
|
||||
// First see if the namespace has an index action
|
||||
PackageConfig.Builder pkgConfig = byNamespace.get(namespace);
|
||||
ActionConfig indexActionConfig = pkgConfig.build().getAllActionConfigs().get("index");
|
||||
if (indexActionConfig == null) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// Step #2
|
||||
if (!redirectToSlash) {
|
||||
int lastSlash = namespace.lastIndexOf('/');
|
||||
if (lastSlash >= 0) {
|
||||
String parentAction = namespace.substring(lastSlash + 1);
|
||||
String parentNamespace = namespace.substring(0, lastSlash);
|
||||
PackageConfig.Builder parent = byNamespace.get(parentNamespace);
|
||||
if (parent == null || parent.build().getAllActionConfigs().get(parentAction) == null) {
|
||||
if (parent == null) {
|
||||
parent = new PackageConfig.Builder(parentNamespace).namespace(parentNamespace).
|
||||
addParents(pkgConfig.build().getParents());
|
||||
packageConfigs.put(parentNamespace, parent);
|
||||
}
|
||||
|
||||
if (parent.build().getAllActionConfigs().get(parentAction) == null) {
|
||||
parent.addActionConfig(parentAction, indexActionConfig);
|
||||
}
|
||||
} else if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("The parent namespace [#0] already contains " +
|
||||
"an action [#1]", parentNamespace, parentAction);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Step #3
|
||||
if (pkgConfig.build().getAllActionConfigs().get("") == null) {
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Creating index ActionConfig with an action name of [] for the action " +
|
||||
"class [#0]", indexActionConfig.getClassName());
|
||||
}
|
||||
|
||||
pkgConfig.addActionConfig("", indexActionConfig);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class has some reflection helpers.
|
||||
* </p>
|
||||
*/
|
||||
public class ReflectionTools {
|
||||
/**
|
||||
* Determines if the class given contains the method.
|
||||
*
|
||||
* @param klass The class to check for the method.
|
||||
* @param method The method name.
|
||||
* @param parameterTypes The parameter types of the method.
|
||||
* @return True if the method exists, false if not.
|
||||
*/
|
||||
public static boolean containsMethod(Class<?> klass, String method, Class<?>... parameterTypes) {
|
||||
try {
|
||||
klass.getMethod(method, parameterTypes);
|
||||
return true;
|
||||
} catch (NoSuchMethodException e) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Retrieves the annotation from the given method in the given class.
|
||||
*
|
||||
* @param klass The class.
|
||||
* @param methodName The method.
|
||||
* @param annotationClass The annotation to get.
|
||||
* @return The annotation or null if it doesn't exist.
|
||||
*/
|
||||
public static <T extends Annotation> T getAnnotation(Class<?> klass, String methodName, Class<T> annotationClass) {
|
||||
try {
|
||||
Method method = klass.getMethod(methodName);
|
||||
return method.getAnnotation(annotationClass);
|
||||
} catch (NoSuchMethodException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,50 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultConfig;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This interface defines how results are constructed for an Action.
|
||||
* The action information is supplied and the result is a mapping of
|
||||
* ResultConfig instances to the result name.
|
||||
* </p>
|
||||
*/
|
||||
public interface ResultMapBuilder {
|
||||
/**
|
||||
* Builds the result configurations given the action information.
|
||||
*
|
||||
* @param actionClass The class of the action.
|
||||
* @param annotation The action annotation.
|
||||
* @param actionName The action name.
|
||||
* @param packageConfig The package configuration that the action will be added to.
|
||||
* @return The mapping of the result names to the result configurations. If there were none found
|
||||
* than this should return an empty Map.
|
||||
*/
|
||||
Map<String, ResultConfig> build(Class<?> actionClass, Action annotation, String actionName,
|
||||
PackageConfig packageConfig);
|
||||
}
|
||||
+94
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import com.opensymphony.xwork2.inject.Inject;
|
||||
import com.opensymphony.xwork2.util.logging.Logger;
|
||||
import com.opensymphony.xwork2.util.logging.LoggerFactory;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class converts the class name into a SEO friendly name by recognizing
|
||||
* camel casing and inserting dashes. This also converts everything to
|
||||
* lower case if desired. And this will also strip off the word <b>Action</b>
|
||||
* from the class name.
|
||||
* </p>
|
||||
*/
|
||||
public class SEOActionNameBuilder implements ActionNameBuilder {
|
||||
private static final Logger LOG = LoggerFactory.getLogger(SEOActionNameBuilder.class);
|
||||
private String actionSuffix = "Action";
|
||||
private boolean lowerCase;
|
||||
private String separator;
|
||||
|
||||
@Inject
|
||||
public SEOActionNameBuilder(@Inject(value="struts.convention.action.name.lowercase") String lowerCase,
|
||||
@Inject(value="struts.convention.action.name.separator") String separator) {
|
||||
this.lowerCase = Boolean.parseBoolean(lowerCase);
|
||||
this.separator = separator;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param actionSuffix (Optional) Classes that end with these value will be mapped as actions
|
||||
* (defaults to "Action")
|
||||
*/
|
||||
@Inject(value = "struts.convention.action.suffix", required = false)
|
||||
public void setActionSuffix(String actionSuffix) {
|
||||
if (!StringTools.isTrimmedEmpty(actionSuffix)) {
|
||||
this.actionSuffix = actionSuffix;
|
||||
}
|
||||
}
|
||||
|
||||
public String build(String className) {
|
||||
String actionName = className;
|
||||
|
||||
// Truncate Action suffix if found
|
||||
if (actionName.endsWith(actionSuffix)) {
|
||||
actionName = actionName.substring(0, actionName.length() - actionSuffix.length());
|
||||
}
|
||||
|
||||
// Convert to underscores
|
||||
char[] ca = actionName.toCharArray();
|
||||
StringBuilder build = new StringBuilder("" + ca[0]);
|
||||
boolean lower = true;
|
||||
for (int i = 1; i < ca.length; i++) {
|
||||
char c = ca[i];
|
||||
if (Character.isUpperCase(c) && lower) {
|
||||
build.append(separator);
|
||||
lower = false;
|
||||
} else if (!Character.isUpperCase(c)) {
|
||||
lower = true;
|
||||
}
|
||||
|
||||
build.append(c);
|
||||
}
|
||||
|
||||
actionName = build.toString();
|
||||
if (lowerCase) {
|
||||
actionName = actionName.toLowerCase();
|
||||
}
|
||||
|
||||
if (LOG.isTraceEnabled()) {
|
||||
LOG.trace("Changed action name from [#0] to [#1]", className, actionName);
|
||||
}
|
||||
|
||||
return actionName;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,86 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import com.opensymphony.xwork2.config.ConfigurationException;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class is a String helper.
|
||||
* </p>
|
||||
*/
|
||||
public class StringTools {
|
||||
public static boolean isTrimmedEmpty(String s) {
|
||||
return s == null || s.trim().length() == 0;
|
||||
}
|
||||
|
||||
public static String lastToken(String str, String s) {
|
||||
int index = str.lastIndexOf(s);
|
||||
if (index >= 0) {
|
||||
return str.substring(index + 1);
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
|
||||
public static boolean contains(String[] strings, String value, boolean ignoreCase) {
|
||||
if (strings != null) {
|
||||
for (String string : strings) {
|
||||
if (string.equals(value) || (ignoreCase && string.equalsIgnoreCase(value)))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
public static String upToLastToken(String str, String s) {
|
||||
int index = str.lastIndexOf(s);
|
||||
if (index >= 0) {
|
||||
return str.substring(0, index);
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
public static Map<String, String> createParameterMap(String[] parms) {
|
||||
Map<String, String> map = new HashMap<String, String>();
|
||||
int subtract = parms.length % 2;
|
||||
if (subtract != 0) {
|
||||
throw new ConfigurationException(
|
||||
"'params' is a string array "
|
||||
+ "and they must be in a key value pair configuration. It looks like you"
|
||||
+ " have specified an odd number of parameters and there should only be an even number."
|
||||
+ " (e.g. params = {\"key\", \"value\"})");
|
||||
}
|
||||
|
||||
for (int i = 0; i < parms.length; i = i + 2) {
|
||||
String key = parms[i];
|
||||
String value = parms[i + 1];
|
||||
map.put(key, value);
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation can be used to control the URL that maps to
|
||||
* a specific method in an Action class. By default, the method
|
||||
* that is invoked is the execute method of the action and the
|
||||
* URL is based on the package and class names. This annotation
|
||||
* allows developers to change the URL or invoke a different
|
||||
* method. This also allows developers to specify multiple URLs
|
||||
* that will be handled by a single class or a single method.
|
||||
* </p>
|
||||
* <p>
|
||||
* This can also be used via the {@link Actions} annotation
|
||||
* to associate multiple URLs with a single method.
|
||||
* </p>
|
||||
* <p>
|
||||
* Here's an example:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* public class MyAction implements Action {
|
||||
* {@code @Action("/foo/bar")}
|
||||
* public String execute() {}
|
||||
* }
|
||||
* </pre>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Target({ElementType.METHOD, ElementType.TYPE})
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Action {
|
||||
String DEFAULT_VALUE = "DEFAULT_VALUE";
|
||||
|
||||
/**
|
||||
* Allows actions to specify different URLs rather than the default that is based on the package
|
||||
* and action name. This also allows methods other than execute() to be invoked or multiple URLs
|
||||
* to map to a single class or a single method to handle multiple URLs.
|
||||
*
|
||||
* @return The action URL.
|
||||
*/
|
||||
String value() default DEFAULT_VALUE;
|
||||
|
||||
/**
|
||||
* Allows action methods to specifically control the results for specific return values. These
|
||||
* results are not used for other method/URL invocations on the action. These are only used for
|
||||
* the URL that this action is associated with.
|
||||
*
|
||||
* @return The results for the action.
|
||||
*/
|
||||
Result[] results() default {};
|
||||
|
||||
/**
|
||||
* Allows action methods to specify what interceptors must be applied to it.
|
||||
* @return Interceptors to be applied to the action
|
||||
*/
|
||||
InterceptorRef[] interceptorRefs() default {};
|
||||
|
||||
/**
|
||||
* @return The parameters passed to the action. This is a list of strings that form a name/value
|
||||
* pair chain since creating a Map for annotations is not possible. An example would be:
|
||||
* <code>{"key", "value", "key2", "value2"}</code>.
|
||||
*/
|
||||
String[] params() default {};
|
||||
|
||||
/**
|
||||
* @return Maps return codes to exceptions. The "exceptions" interceptor must be applied to the action.
|
||||
*/
|
||||
ExceptionMapping[] exceptionMappings() default {};
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation allows for multiple {@link Action} annotations
|
||||
* to be used on a single method.
|
||||
* </p>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
public @interface Actions {
|
||||
Action[] value() default {};
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class provides helper methods for dealing with annotations.
|
||||
* </p>
|
||||
*/
|
||||
public class AnnotationTools {
|
||||
|
||||
/**
|
||||
* Returns the annotation on the given class or the package of the class. This searchs up the
|
||||
* class hierarchy and the package hierarchy.
|
||||
*
|
||||
* @param klass The class to search for the annotation.
|
||||
* @param annotationClass The Class of the annotation.
|
||||
* @return The annotation or null.
|
||||
*/
|
||||
public static <T extends Annotation> T findAnnotation(Class<?> klass, Class<T> annotationClass) {
|
||||
T ann = klass.getAnnotation(annotationClass);
|
||||
while (ann == null && klass != null) {
|
||||
ann = klass.getPackage().getAnnotation(annotationClass);
|
||||
if (ann == null) {
|
||||
klass = klass.getSuperclass();
|
||||
}
|
||||
}
|
||||
|
||||
return ann;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Defines the default interceptor for all actions
|
||||
* in this package
|
||||
*/
|
||||
@Target({ElementType.PACKAGE})
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
public @interface DefaultInterceptorRef {
|
||||
/**
|
||||
* @return The interceptor name.
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
+54
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* Adds an exception mapping to an action
|
||||
* </p>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ExceptionMapping {
|
||||
/**
|
||||
* @return Result name
|
||||
*/
|
||||
String result();
|
||||
|
||||
/**
|
||||
* @return Class name of the exception to be thrown
|
||||
*/
|
||||
String exception();
|
||||
|
||||
/**
|
||||
* @return The parameters passed to the exception. This is a list of strings that form a name/value
|
||||
* pair chain since creating a Map for annotations is not possible. An example would be:
|
||||
* <code>{"key", "value", "key2", "value2"}</code>.
|
||||
*/
|
||||
String[] params() default {};
|
||||
}
|
||||
+44
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation allows a class to define more than one {@link ExceptionMapping}
|
||||
* annotations. These exception mappings will be on all actions defined in the annotated
|
||||
* class, they are not global exception mappings.
|
||||
* </p>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface ExceptionMappings {
|
||||
/**
|
||||
* @return Exception mappings
|
||||
*/
|
||||
ExceptionMapping[] value();
|
||||
}
|
||||
+52
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation allows an interceptor to be applied to an action. If
|
||||
* this annotation is used at the class level, then the interceptor
|
||||
* will be applied to all actions defined on that class, and will be applied
|
||||
* before the ones defined at the method level.
|
||||
* </p>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.TYPE)
|
||||
public @interface InterceptorRef {
|
||||
/**
|
||||
* @return name of the interceptor or interceptor stack
|
||||
*/
|
||||
String value();
|
||||
|
||||
/**
|
||||
* @return The parameters passed to the interceptor. This is a list of strings that form a name/value
|
||||
* pair chain, since creating a Map for annotations is not possible. An example would be:
|
||||
* <code>{"key", "value", "key2", "value2"}</code>.
|
||||
*/
|
||||
String[] params() default {};
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation allows a class to define more than one {@link InterceptorRef}
|
||||
* annotations.
|
||||
* </p>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface InterceptorRefs {
|
||||
InterceptorRef[] value();
|
||||
}
|
||||
+93
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.annotation.ElementType;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation defines how actions can modify the namespace
|
||||
* that they are added to. This overrides the behavior of the
|
||||
* Convention plugin which by default uses the package names for
|
||||
* namespaces. Since XWork packages are created by the Convention
|
||||
* plugin via the Java packages that the actions exist in, there
|
||||
* is some tricky handling of XWork parent packages and namespaces
|
||||
* of the XWork packages for the Convention plugin discovered
|
||||
* actions so that two actions in the same package can specify
|
||||
* different parents and namespaces without collision.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* In order to handle this correctly, the name of the XWork
|
||||
* package that actions are placed into is built using this
|
||||
* format:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* <java-package>#<parent-xwork-package>#<namespace>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* This mechanism will guarantee that two actions in the same
|
||||
* Java package can specify different parent packages (using the
|
||||
* {@link org.apache.struts2.convention.annotation.ParentPackage} annotation)
|
||||
* and namespaces (using this annotation).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* The value of a Namespace annotation should specify the portion of
|
||||
* the action URL between the context path and the action name. For
|
||||
* example:
|
||||
* </p>
|
||||
* <pre>
|
||||
* @Namespace("/careers/job-postings-overview/job-postings")
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* This annotation can also be placed inside the special Java file
|
||||
* named <strong>package-info.java</strong>, which allows package
|
||||
* level annotations. If this is used in this manner it changes the
|
||||
* default namespace for all actions within that Java package. The
|
||||
* search order for the namespace of a particular class is therefore:
|
||||
* </p>
|
||||
*
|
||||
* <ol>
|
||||
* <li>If the {@link Action} annotation exists within the action and
|
||||
* specifies a full URI (i.e. it starts with a / character)</li>
|
||||
* <li>Any Namespace annotations placed on individual action classes</li>
|
||||
* <li>Any Namespace annotations placed in the package-info.java file</li>
|
||||
* <li>The namespace as determined using the Java package name and the
|
||||
* standard convention based naming.</li>
|
||||
* </ol>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Target({ElementType.PACKAGE, ElementType.TYPE})
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
public @interface Namespace {
|
||||
/**
|
||||
* @return The namespace value.
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation allows actions to be defined in more than one {@link Namespace}
|
||||
* </p>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Target({ElementType.PACKAGE, ElementType.TYPE})
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
public @interface Namespaces {
|
||||
Namespace[] value();
|
||||
}
|
||||
+78
@@ -0,0 +1,78 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation allows actions to modify the parent package
|
||||
* that they are using. Since XWork packages are created by
|
||||
* the Convention plugin via the Java packages that the actions
|
||||
* exist in, there is some tricky handling of XWork parent packages
|
||||
* and namespaces of the XWork packages for discovered
|
||||
* actions so that two actions in the same package can specify
|
||||
* different parents and namespaces without collision.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* In order to handle this correctly, the name of the XWork
|
||||
* package that actions are placed into is built using this
|
||||
* format:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* <java-package>#<parent-xwork-package>#<namespace>
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* This mechanism will guarantee that two actions in the same
|
||||
* Java package can specify different parent packages (using this
|
||||
* annotation) and namespaces (using the {@link Namespace} annotation).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This annotation can be used directly on Action classes or
|
||||
* in the <strong>package-info.java</strong> class in order
|
||||
* to specify the default XWork parent package for all actions
|
||||
* in the Java package. The search order for XWork parent packages
|
||||
* is therefore:
|
||||
* </p>
|
||||
*
|
||||
* <ol>
|
||||
* <li>Any ParentPackage annotations placed on individual action classes</li>
|
||||
* <li>Any ParentPackage annotations placed in the package-info.java file</li>
|
||||
* <li>The struts configuration property <strong>struts.convention.default.parent.package</strong></li>
|
||||
* </ol>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Target({ElementType.TYPE, ElementType.PACKAGE})
|
||||
@Retention(value = RetentionPolicy.RUNTIME)
|
||||
public @interface ParentPackage {
|
||||
/**
|
||||
* @return The parent package.
|
||||
*/
|
||||
String value();
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation is used to specify non-convention based results for
|
||||
* the Struts convention handling. This annotation is added to a class
|
||||
* and can be used to specify the result location for a specific result
|
||||
* code from an action method. Furthermore, this can also be used to
|
||||
* handle results only for specific action methods within an action class
|
||||
* (if there are multiple).
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* When this annotation is used on an action class, it generates results
|
||||
* that are applicable to all of the actions URLs defined in the class.
|
||||
* These are considered global results for that class. Here is an example
|
||||
* of a global result:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* {@code @Result(name="fail", location="failed.jsp")}
|
||||
* public class MyAction {
|
||||
* }
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* This annotation can also be used inside an {@link Action} annotation
|
||||
* on specific methods. This usage will define results for that specific
|
||||
* action URL. Here is an example of an action URL specific result:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* {@code @Action(results={@Result(name="success", location="/", type="redirect")})}
|
||||
* public String execute() {
|
||||
* }
|
||||
* </pre>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface Result {
|
||||
/**
|
||||
* @return The name of the result mapping. This is the value that is returned from the action
|
||||
* method and is used to associate a location with a return value.
|
||||
*/
|
||||
String name();
|
||||
|
||||
/**
|
||||
* @return The location of the result within the web application or anywhere on disk. This location
|
||||
* can be relative if the type of this result is one of the pre-defined relative result
|
||||
* types (these default to dispatcher, velocity and freemarker). Or this location can be
|
||||
* absolute relative to the root of the web application or the classpath (since velocity
|
||||
* and freemarker templates can be loaded via the classpath).
|
||||
*/
|
||||
String location() default "";
|
||||
|
||||
/**
|
||||
* @return The type of the result. This is usually setup in the struts.xml or struts-plugin.xml
|
||||
* and is a simple name that is mapped to a result Class.
|
||||
*/
|
||||
String type() default "";
|
||||
|
||||
/**
|
||||
* @return The parameters passed to the result. This is a list of strings that form a name/value
|
||||
* pair chain since creating a Map for annotations is not possible. An example would be:
|
||||
* <code>{"key", "value", "key2", "value2"}</code>.
|
||||
*/
|
||||
String[] params() default {};
|
||||
}
|
||||
+75
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation allows the path to the results be to changed on a class
|
||||
* by class basis. This will favor the property name setting and then the
|
||||
* value.
|
||||
* </p>
|
||||
*
|
||||
* <p>
|
||||
* This is used when locating results for an action. In most cases a result
|
||||
* is a JSP or some type of template (Velocity for example). In order to
|
||||
* figure out which results are associated with an action, this class can be
|
||||
* used to set the base directory that the Convention plugin looks at when
|
||||
* trying to figure out the correct results. For example, if there is an action:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* com.example.foo.DoSomething
|
||||
* </pre>
|
||||
*
|
||||
* <p>
|
||||
* The Convention plugin might find that the namespace is foo and the action
|
||||
* name is do-something and will need to find the results. Using this annotation
|
||||
* you can set the base path of the results to something like
|
||||
* <code>/WEB-INF/jsps</code> so that the Convention plugin will look in the
|
||||
* web application for files of this pattern:
|
||||
* </p>
|
||||
*
|
||||
* <pre>
|
||||
* /WEB-INF/jsps/foo/do-something-<resultCode>.ext
|
||||
* </pre>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE, ElementType.PACKAGE})
|
||||
public @interface ResultPath {
|
||||
/**
|
||||
* @return The result path to use for this action, instead of the default.
|
||||
*/
|
||||
String value() default "";
|
||||
|
||||
/**
|
||||
* @return The name of the property from the struts.properties file that contains the result
|
||||
* path for the action that contains this annotation. This property must be set
|
||||
* and the struts.properties file must exist in the root of the classpath.
|
||||
*/
|
||||
String property() default "";
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* <!-- START SNIPPET: javadoc -->
|
||||
* <p>
|
||||
* This annotation allows a class to define more than one {@link Result}
|
||||
* annotations.
|
||||
* </p>
|
||||
* <!-- END SNIPPET: javadoc -->
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target({ElementType.TYPE})
|
||||
public @interface Results {
|
||||
Result[] value();
|
||||
}
|
||||
@@ -0,0 +1,174 @@
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
http://www.apache.org/licenses/
|
||||
|
||||
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
|
||||
|
||||
1. Definitions.
|
||||
|
||||
"License" shall mean the terms and conditions for use, reproduction,
|
||||
and distribution as defined by Sections 1 through 9 of this document.
|
||||
|
||||
"Licensor" shall mean the copyright owner or entity authorized by
|
||||
the copyright owner that is granting the License.
|
||||
|
||||
"Legal Entity" shall mean the union of the acting entity and all
|
||||
other entities that control, are controlled by, or are under common
|
||||
control with that entity. For the purposes of this definition,
|
||||
"control" means (i) the power, direct or indirect, to cause the
|
||||
direction or management of such entity, whether by contract or
|
||||
otherwise, or (ii) ownership of fifty percent (50%) or more of the
|
||||
outstanding shares, or (iii) beneficial ownership of such entity.
|
||||
|
||||
"You" (or "Your") shall mean an individual or Legal Entity
|
||||
exercising permissions granted by this License.
|
||||
|
||||
"Source" form shall mean the preferred form for making modifications,
|
||||
including but not limited to software source code, documentation
|
||||
source, and configuration files.
|
||||
|
||||
"Object" form shall mean any form resulting from mechanical
|
||||
transformation or translation of a Source form, including but
|
||||
not limited to compiled object code, generated documentation,
|
||||
and conversions to other media types.
|
||||
|
||||
"Work" shall mean the work of authorship, whether in Source or
|
||||
Object form, made available under the License, as indicated by a
|
||||
copyright notice that is included in or attached to the work
|
||||
(an example is provided in the Appendix below).
|
||||
|
||||
"Derivative Works" shall mean any work, whether in Source or Object
|
||||
form, that is based on (or derived from) the Work and for which the
|
||||
editorial revisions, annotations, elaborations, or other modifications
|
||||
represent, as a whole, an original work of authorship. For the purposes
|
||||
of this License, Derivative Works shall not include works that remain
|
||||
separable from, or merely link (or bind by name) to the interfaces of,
|
||||
the Work and Derivative Works thereof.
|
||||
|
||||
"Contribution" shall mean any work of authorship, including
|
||||
the original version of the Work and any modifications or additions
|
||||
to that Work or Derivative Works thereof, that is intentionally
|
||||
submitted to Licensor for inclusion in the Work by the copyright owner
|
||||
or by an individual or Legal Entity authorized to submit on behalf of
|
||||
the copyright owner. For the purposes of this definition, "submitted"
|
||||
means any form of electronic, verbal, or written communication sent
|
||||
to the Licensor or its representatives, including but not limited to
|
||||
communication on electronic mailing lists, source code control systems,
|
||||
and issue tracking systems that are managed by, or on behalf of, the
|
||||
Licensor for the purpose of discussing and improving the Work, but
|
||||
excluding communication that is conspicuously marked or otherwise
|
||||
designated in writing by the copyright owner as "Not a Contribution."
|
||||
|
||||
"Contributor" shall mean Licensor and any individual or Legal Entity
|
||||
on behalf of whom a Contribution has been received by Licensor and
|
||||
subsequently incorporated within the Work.
|
||||
|
||||
2. Grant of Copyright License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
copyright license to reproduce, prepare Derivative Works of,
|
||||
publicly display, publicly perform, sublicense, and distribute the
|
||||
Work and such Derivative Works in Source or Object form.
|
||||
|
||||
3. Grant of Patent License. Subject to the terms and conditions of
|
||||
this License, each Contributor hereby grants to You a perpetual,
|
||||
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
|
||||
(except as stated in this section) patent license to make, have made,
|
||||
use, offer to sell, sell, import, and otherwise transfer the Work,
|
||||
where such license applies only to those patent claims licensable
|
||||
by such Contributor that are necessarily infringed by their
|
||||
Contribution(s) alone or by combination of their Contribution(s)
|
||||
with the Work to which such Contribution(s) was submitted. If You
|
||||
institute patent litigation against any entity (including a
|
||||
cross-claim or counterclaim in a lawsuit) alleging that the Work
|
||||
or a Contribution incorporated within the Work constitutes direct
|
||||
or contributory patent infringement, then any patent licenses
|
||||
granted to You under this License for that Work shall terminate
|
||||
as of the date such litigation is filed.
|
||||
|
||||
4. Redistribution. You may reproduce and distribute copies of the
|
||||
Work or Derivative Works thereof in any medium, with or without
|
||||
modifications, and in Source or Object form, provided that You
|
||||
meet the following conditions:
|
||||
|
||||
(a) You must give any other recipients of the Work or
|
||||
Derivative Works a copy of this License; and
|
||||
|
||||
(b) You must cause any modified files to carry prominent notices
|
||||
stating that You changed the files; and
|
||||
|
||||
(c) You must retain, in the Source form of any Derivative Works
|
||||
that You distribute, all copyright, patent, trademark, and
|
||||
attribution notices from the Source form of the Work,
|
||||
excluding those notices that do not pertain to any part of
|
||||
the Derivative Works; and
|
||||
|
||||
(d) If the Work includes a "NOTICE" text file as part of its
|
||||
distribution, then any Derivative Works that You distribute must
|
||||
include a readable copy of the attribution notices contained
|
||||
within such NOTICE file, excluding those notices that do not
|
||||
pertain to any part of the Derivative Works, in at least one
|
||||
of the following places: within a NOTICE text file distributed
|
||||
as part of the Derivative Works; within the Source form or
|
||||
documentation, if provided along with the Derivative Works; or,
|
||||
within a display generated by the Derivative Works, if and
|
||||
wherever such third-party notices normally appear. The contents
|
||||
of the NOTICE file are for informational purposes only and
|
||||
do not modify the License. You may add Your own attribution
|
||||
notices within Derivative Works that You distribute, alongside
|
||||
or as an addendum to the NOTICE text from the Work, provided
|
||||
that such additional attribution notices cannot be construed
|
||||
as modifying the License.
|
||||
|
||||
You may add Your own copyright statement to Your modifications and
|
||||
may provide additional or different license terms and conditions
|
||||
for use, reproduction, or distribution of Your modifications, or
|
||||
for any such Derivative Works as a whole, provided Your use,
|
||||
reproduction, and distribution of the Work otherwise complies with
|
||||
the conditions stated in this License.
|
||||
|
||||
5. Submission of Contributions. Unless You explicitly state otherwise,
|
||||
any Contribution intentionally submitted for inclusion in the Work
|
||||
by You to the Licensor shall be under the terms and conditions of
|
||||
this License, without any additional terms or conditions.
|
||||
Notwithstanding the above, nothing herein shall supersede or modify
|
||||
the terms of any separate license agreement you may have executed
|
||||
with Licensor regarding such Contributions.
|
||||
|
||||
6. Trademarks. This License does not grant permission to use the trade
|
||||
names, trademarks, service marks, or product names of the Licensor,
|
||||
except as required for reasonable and customary use in describing the
|
||||
origin of the Work and reproducing the content of the NOTICE file.
|
||||
|
||||
7. Disclaimer of Warranty. Unless required by applicable law or
|
||||
agreed to in writing, Licensor provides the Work (and each
|
||||
Contributor provides its Contributions) on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
|
||||
implied, including, without limitation, any warranties or conditions
|
||||
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
|
||||
PARTICULAR PURPOSE. You are solely responsible for determining the
|
||||
appropriateness of using or redistributing the Work and assume any
|
||||
risks associated with Your exercise of permissions under this License.
|
||||
|
||||
8. Limitation of Liability. In no event and under no legal theory,
|
||||
whether in tort (including negligence), contract, or otherwise,
|
||||
unless required by applicable law (such as deliberate and grossly
|
||||
negligent acts) or agreed to in writing, shall any Contributor be
|
||||
liable to You for damages, including any direct, indirect, special,
|
||||
incidental, or consequential damages of any character arising as a
|
||||
result of this License or out of the use or inability to use the
|
||||
Work (including but not limited to damages for loss of goodwill,
|
||||
work stoppage, computer failure or malfunction, or any and all
|
||||
other commercial damages or losses), even if such Contributor
|
||||
has been advised of the possibility of such damages.
|
||||
|
||||
9. Accepting Warranty or Additional Liability. While redistributing
|
||||
the Work or Derivative Works thereof, You may choose to offer,
|
||||
and charge a fee for, acceptance of support, warranty, indemnity,
|
||||
or other liability obligations and/or rights consistent with this
|
||||
License. However, in accepting such obligations, You may act only
|
||||
on Your own behalf and on Your sole responsibility, not on behalf
|
||||
of any other Contributor, and only if You agree to indemnify,
|
||||
defend, and hold each Contributor harmless for any liability
|
||||
incurred by, or claims asserted against, such Contributor by reason
|
||||
of your accepting any such warranty or additional liability.
|
||||
@@ -0,0 +1,5 @@
|
||||
Apache Struts
|
||||
Copyright 2000-2007 The Apache Software Foundation
|
||||
|
||||
This product includes software developed by
|
||||
The Apache Software Foundation (http://www.apache.org/).
|
||||
@@ -0,0 +1,60 @@
|
||||
<?xml version="1.0" encoding="UTF-8" ?>
|
||||
<!--
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
-->
|
||||
|
||||
<!DOCTYPE struts PUBLIC
|
||||
"-//Apache Software Foundation//DTD Struts Configuration 2.0//EN"
|
||||
"http://struts.apache.org/dtds/struts-2.0.dtd">
|
||||
|
||||
<struts>
|
||||
<bean type="com.opensymphony.xwork2.UnknownHandler" class="org.apache.struts2.convention.ConventionUnknownHandler"/>
|
||||
|
||||
<bean type="org.apache.struts2.convention.ActionConfigBuilder" class="org.apache.struts2.convention.PackageBasedActionConfigBuilder"/>
|
||||
<bean type="org.apache.struts2.convention.ActionNameBuilder" class="org.apache.struts2.convention.SEOActionNameBuilder"/>
|
||||
<bean type="org.apache.struts2.convention.ResultMapBuilder" class="org.apache.struts2.convention.DefaultResultMapBuilder"/>
|
||||
<bean type="org.apache.struts2.convention.InterceptorMapBuilder" class="org.apache.struts2.convention.DefaultInterceptorMapBuilder"/>
|
||||
<bean type="org.apache.struts2.convention.ConventionsService" class="org.apache.struts2.convention.ConventionsServiceImpl"/>
|
||||
|
||||
<bean type="com.opensymphony.xwork2.config.PackageProvider" class="org.apache.struts2.convention.ClasspathConfigurationProvider"/>
|
||||
|
||||
<constant name="struts.convention.result.path" value="/WEB-INF/content/"/>
|
||||
<constant name="struts.convention.result.flatLayout" value="true"/>
|
||||
<constant name="struts.convention.action.suffix" value="Action"/>
|
||||
<constant name="struts.convention.action.disableScanning" value="false"/>
|
||||
<constant name="struts.convention.action.disableJarScanning" value="true"/>
|
||||
<constant name="struts.convention.action.mapAllMatches" value="false"/>
|
||||
<constant name="struts.convention.action.checkImplementsAction" value="true"/>
|
||||
<constant name="struts.convention.default.parent.package" value="convention-default"/>
|
||||
<constant name="struts.convention.action.name.lowercase" value="true"/>
|
||||
<constant name="struts.convention.action.name.separator" value="-"/>
|
||||
<constant name="struts.convention.package.locators" value="action,actions,struts,struts2"/>
|
||||
<constant name="struts.convention.package.locators.disable" value="false"/>
|
||||
<constant name="struts.convention.package.locators.basePackage" value=""/>
|
||||
<constant name="struts.convention.exclude.packages" value="org.apache.struts.*,org.apache.struts2.*,org.springframework.web.struts.*,org.springframework.web.struts2.*,org.hibernate.*"/>
|
||||
<constant name="struts.convention.relative.result.types" value="dispatcher,velocity,freemarker"/>
|
||||
<constant name="struts.convention.redirect.to.slash" value="true"/>
|
||||
<constant name="struts.mapper.alwaysSelectFullNamespace" value="true"/>
|
||||
|
||||
<package name="convention-default" extends="struts-default">
|
||||
</package>
|
||||
</struts>
|
||||
@@ -0,0 +1,18 @@
|
||||
struts.convention.action.excludeJars = .*/activemq-(core|ra)-[\\d.]+.jar(!/)?, \
|
||||
.*/catalina.*?jar(!/)?, \
|
||||
.*/tomcat.*?jar(!/)?, \
|
||||
.*/junit-[\\d.]+.jar(!/)?, \
|
||||
.*/log4j-[\\d.]+.jar(!/)?, \
|
||||
.*/xwork-[\\d.]+.jar(!/)?, \
|
||||
.*/ognl-[\\d.]+.jar(!/)?, \
|
||||
.*/aopalliance-[\\d.]+.jar(!/)?, \
|
||||
.*/jstl-[\\d.]+.jar(!/)?, \
|
||||
.*/dwr-[\\d.]+.jar(!/)?, \
|
||||
.*/freemarker-[\\d.]+.jar(!/)?, \
|
||||
.*/servlet-api-[\\d.]+.jar(!/)?, \
|
||||
.*/sitemesh-[\\d.]+.jar(!/)?, \
|
||||
.*/commons-(beanutils|el|digester|fileupload|codec|chain|logging|cli|pool|lang|collections|dbcp)-[\\d.]+.jar(!/)?, \
|
||||
.*/spring-(beans|context|core|mock|web|jdbc)-[\\d.]+.jar(!/)?, \
|
||||
.*/velocity-[\\d.]+.jar(!/)?, \
|
||||
.*/velocity-(dep|tools)-[\\d.]+.jar(!/)?, \
|
||||
.*/struts2-(config-browser-plugin|core|dojo-plugin|dwr-plugin|jsf-plugin|sitemesh-plugin|spring-plugin|struts1-plugin|tiles-plugin)-[\\d.]+.jar(!/)?
|
||||
+327
@@ -0,0 +1,327 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import static org.apache.struts2.convention.ReflectionTools.*;
|
||||
import org.apache.struts2.convention.actions.NoAnnotationAction;
|
||||
import org.apache.struts2.convention.actions.result.ActionLevelResultAction;
|
||||
import org.apache.struts2.convention.actions.result.ActionLevelResultsAction;
|
||||
import org.apache.struts2.convention.actions.result.ClassLevelResultAction;
|
||||
import org.apache.struts2.convention.actions.result.ClassLevelResultsAction;
|
||||
import org.apache.struts2.convention.actions.resultpath.ClassLevelResultPathAction;
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.easymock.EasyMock;
|
||||
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class tests the simple result map builder.
|
||||
* </p>
|
||||
*/
|
||||
public class DefaultResultMapBuilderTest extends TestCase {
|
||||
public void testBuild() throws Exception {
|
||||
ServletContext context = mockServletContext("/WEB-INF/location");
|
||||
|
||||
// Test with a slash
|
||||
PackageConfig packageConfig = createPackageConfigBuilder("/namespace");
|
||||
DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, new ConventionsServiceImpl("/WEB-INF/location"), "dispatcher,velocity,freemarker");
|
||||
Map<String, ResultConfig> results = builder.build(NoAnnotationAction.class, null, "action", packageConfig);
|
||||
verify(context, "/WEB-INF/location", results, false);
|
||||
|
||||
// Test without a slash
|
||||
context = mockServletContext("/WEB-INF/location");
|
||||
packageConfig = createPackageConfigBuilder("namespace");
|
||||
builder = new DefaultResultMapBuilder(context, new ConventionsServiceImpl("/WEB-INF/location"), "dispatcher,velocity,freemarker");
|
||||
results = builder.build(NoAnnotationAction.class, null, "action", packageConfig);
|
||||
verify(context, "/WEB-INF/location", results, false);
|
||||
}
|
||||
|
||||
public void testNull() throws Exception {
|
||||
ServletContext context = EasyMock.createStrictMock(ServletContext.class);
|
||||
EasyMock.expect(context.getResourcePaths("/WEB-INF/location/namespace/")).andReturn(null);
|
||||
EasyMock.replay(context);
|
||||
|
||||
// Test with a slash
|
||||
PackageConfig packageConfig = createPackageConfigBuilder("/namespace");
|
||||
DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, new ConventionsServiceImpl("/WEB-INF/location"), "dispatcher,velocity,freemarker");
|
||||
Map<String, ResultConfig> results = builder.build(NoAnnotationAction.class, null, "action", packageConfig);
|
||||
assertEquals(0, results.size());
|
||||
EasyMock.verify(context);
|
||||
}
|
||||
|
||||
public void testResultPath() throws Exception {
|
||||
ServletContext context = mockServletContext("/class-level");
|
||||
|
||||
// Test with a result path
|
||||
PackageConfig packageConfig = createPackageConfigBuilder("/namespace");
|
||||
DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, new ConventionsServiceImpl("/not-used"), "dispatcher,velocity,freemarker");
|
||||
Map<String, ResultConfig> results = builder.build(ClassLevelResultPathAction.class, null, "action", packageConfig);
|
||||
verify(context, "/class-level", results, false);
|
||||
}
|
||||
|
||||
public void testFromServletContext() throws Exception {
|
||||
ServletContext context = EasyMock.createStrictMock(ServletContext.class);
|
||||
|
||||
// Setup some mock jsps
|
||||
Set<String> resources = new HashSet<String>();
|
||||
resources.add("/WEB-INF/location/namespace/no-annotation.ftl");
|
||||
resources.add("/WEB-INF/location/namespace/no-annotation-success.jsp");
|
||||
resources.add("/WEB-INF/location/namespace/no-annotation-failure.jsp");
|
||||
EasyMock.expect(context.getResourcePaths("/WEB-INF/location/namespace/")).andReturn(resources);
|
||||
EasyMock.replay(context);
|
||||
|
||||
PackageConfig packageConfig = createPackageConfigBuilder("/namespace");
|
||||
|
||||
DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, new ConventionsServiceImpl("/WEB-INF/location"), "dispatcher,velocity,freemarker");
|
||||
Map<String, ResultConfig> results = builder.build(NoAnnotationAction.class, null, "no-annotation", packageConfig);
|
||||
assertEquals(4, results.size());
|
||||
assertEquals("success", results.get("success").getName());
|
||||
assertEquals(3, results.get("success").getParams().size());
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
|
||||
assertEquals("/WEB-INF/location/namespace/no-annotation-success.jsp", results.get("success").getParams().get("location"));
|
||||
assertEquals(1, results.get("input").getParams().size());
|
||||
assertEquals("org.apache.struts2.views.freemarker.FreemarkerResult", results.get("input").getClassName());
|
||||
assertEquals("/WEB-INF/location/namespace/no-annotation.ftl", results.get("input").getParams().get("location"));
|
||||
assertEquals(1, results.get("error").getParams().size());
|
||||
assertEquals("org.apache.struts2.views.freemarker.FreemarkerResult", results.get("error").getClassName());
|
||||
assertEquals("/WEB-INF/location/namespace/no-annotation.ftl", results.get("error").getParams().get("location"));
|
||||
assertEquals(3, results.get("failure").getParams().size());
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
|
||||
assertEquals("/WEB-INF/location/namespace/no-annotation-failure.jsp", results.get("failure").getParams().get("location"));
|
||||
EasyMock.verify(context);
|
||||
|
||||
}
|
||||
|
||||
public void testClassLevelSingleResultAnnotation() throws Exception {
|
||||
ServletContext context = EasyMock.createStrictMock(ServletContext.class);
|
||||
|
||||
// Setup some mock jsps
|
||||
Set<String> resources = new HashSet<String>();
|
||||
EasyMock.expect(context.getResourcePaths("/WEB-INF/location/namespace/")).andReturn(resources);
|
||||
EasyMock.replay(context);
|
||||
|
||||
PackageConfig packageConfig = createPackageConfigBuilder("/namespace");
|
||||
|
||||
DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, new ConventionsServiceImpl("/WEB-INF/location"), "dispatcher,velocity,freemarker");
|
||||
Map<String, ResultConfig> results = builder.build(ClassLevelResultAction.class, null, "class-level-result", packageConfig);
|
||||
assertEquals(1, results.size());
|
||||
assertEquals("error", results.get("error").getName());
|
||||
assertEquals(3, results.get("error").getParams().size());
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("error").getClassName());
|
||||
assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location"));
|
||||
assertEquals("value", results.get("error").getParams().get("key"));
|
||||
assertEquals("value1", results.get("error").getParams().get("key1"));
|
||||
EasyMock.verify(context);
|
||||
}
|
||||
|
||||
public void testClassLevelMultipleResultAnnotation() throws Exception {
|
||||
ServletContext context = EasyMock.createStrictMock(ServletContext.class);
|
||||
|
||||
// Setup some mock jsps
|
||||
Set<String> resources = new HashSet<String>();
|
||||
EasyMock.expect(context.getResourcePaths("/WEB-INF/location/namespace/")).andReturn(resources);
|
||||
EasyMock.replay(context);
|
||||
|
||||
PackageConfig packageConfig = createPackageConfigBuilder("/namespace");
|
||||
|
||||
DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, new ConventionsServiceImpl("/WEB-INF/location"), "dispatcher,velocity,freemarker");
|
||||
Map<String, ResultConfig> results = builder.build(ClassLevelResultsAction.class, null, "class-level-results", packageConfig);
|
||||
assertEquals(4, results.size());
|
||||
assertEquals("error", results.get("error").getName());
|
||||
assertEquals("input", results.get("input").getName());
|
||||
assertEquals("success", results.get("success").getName());
|
||||
assertEquals("failure", results.get("failure").getName());
|
||||
assertEquals(3, results.get("error").getParams().size());
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("error").getClassName());
|
||||
assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location"));
|
||||
assertEquals("ann-value", results.get("error").getParams().get("key"));
|
||||
assertEquals("ann-value1", results.get("error").getParams().get("key1"));
|
||||
assertEquals(1, results.get("input").getParams().size());
|
||||
assertEquals("foo.action", results.get("input").getParams().get("actionName"));
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletActionRedirectResult", results.get("input").getClassName());
|
||||
assertEquals(3, results.get("failure").getParams().size());
|
||||
assertEquals("/WEB-INF/location/namespace/action-failure.jsp", results.get("failure").getParams().get("location"));
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("failure").getClassName());
|
||||
assertEquals("value", results.get("failure").getParams().get("key"));
|
||||
assertEquals("value1", results.get("failure").getParams().get("key1"));
|
||||
assertEquals(3, results.get("success").getParams().size());
|
||||
assertEquals("/WEB-INF/location/namespace/action-success.jsp", results.get("success").getParams().get("location"));
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
|
||||
assertEquals("value", results.get("success").getParams().get("key"));
|
||||
assertEquals("value1", results.get("success").getParams().get("key1"));
|
||||
EasyMock.verify(context);
|
||||
}
|
||||
|
||||
public void testActionLevelSingleResultAnnotation() throws Exception {
|
||||
ServletContext context = EasyMock.createStrictMock(ServletContext.class);
|
||||
|
||||
// Setup some mock jsps
|
||||
Set<String> resources = new HashSet<String>();
|
||||
EasyMock.expect(context.getResourcePaths("/WEB-INF/location/namespace/")).andReturn(resources);
|
||||
EasyMock.replay(context);
|
||||
|
||||
PackageConfig packageConfig = createPackageConfigBuilder("/namespace");
|
||||
|
||||
DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, new ConventionsServiceImpl("/WEB-INF/location"), "dispatcher,velocity,freemarker");
|
||||
Map<String, ResultConfig> results = builder.build(ActionLevelResultAction.class, getAnnotation(ActionLevelResultAction.class, "execute", Action.class), "action-level-result", packageConfig);
|
||||
assertEquals(1, results.size());
|
||||
assertEquals("success", results.get("success").getName());
|
||||
assertEquals(3, results.get("success").getParams().size());
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
|
||||
assertEquals("/WEB-INF/location/namespace/action-success.jsp", results.get("success").getParams().get("location"));
|
||||
assertEquals("value", results.get("success").getParams().get("key"));
|
||||
assertEquals("value1", results.get("success").getParams().get("key1"));
|
||||
EasyMock.verify(context);
|
||||
}
|
||||
|
||||
public void testActionLevelMultipleResultAnnotation() throws Exception {
|
||||
ServletContext context = EasyMock.createStrictMock(ServletContext.class);
|
||||
|
||||
// Setup some mock jsps
|
||||
Set<String> resources = new HashSet<String>();
|
||||
EasyMock.expect(context.getResourcePaths("/WEB-INF/location/namespace/")).andReturn(resources);
|
||||
EasyMock.replay(context);
|
||||
|
||||
PackageConfig packageConfig = createPackageConfigBuilder("/namespace");
|
||||
|
||||
DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, new ConventionsServiceImpl("/WEB-INF/location"), "dispatcher,velocity,freemarker");
|
||||
Map<String, ResultConfig> results = builder.build(ActionLevelResultsAction.class, getAnnotation(ActionLevelResultsAction.class, "execute", Action.class), "action-level-results", packageConfig);
|
||||
assertEquals(4, results.size());
|
||||
assertEquals("error", results.get("error").getName());
|
||||
assertEquals("input", results.get("input").getName());
|
||||
assertEquals("success", results.get("success").getName());
|
||||
assertEquals("failure", results.get("failure").getName());
|
||||
assertEquals(3, results.get("error").getParams().size());
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("error").getClassName());
|
||||
assertEquals("/WEB-INF/location/namespace/error.jsp", results.get("error").getParams().get("location"));
|
||||
assertEquals("value", results.get("success").getParams().get("key"));
|
||||
assertEquals("value1", results.get("success").getParams().get("key1"));
|
||||
assertEquals(1, results.get("input").getParams().size());
|
||||
assertEquals("foo.action", results.get("input").getParams().get("actionName"));
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletActionRedirectResult", results.get("input").getClassName());
|
||||
assertEquals(3, results.get("failure").getParams().size());
|
||||
assertEquals("/WEB-INF/location/namespace/action-failure.jsp", results.get("failure").getParams().get("location"));
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("failure").getClassName());
|
||||
assertEquals(3, results.get("success").getParams().size());
|
||||
assertEquals("/WEB-INF/location/namespace/action-success.jsp", results.get("success").getParams().get("location"));
|
||||
assertEquals("org.apache.struts2.dispatcher.ServletDispatcherResult", results.get("success").getClassName());
|
||||
EasyMock.verify(context);
|
||||
}
|
||||
|
||||
public void testClassPath() throws Exception {
|
||||
ServletContext context = EasyMock.createNiceMock(ServletContext.class);
|
||||
|
||||
ResultTypeConfig resultType = new ResultTypeConfig.Builder("freemarker", "org.apache.struts2.dispatcher.ServletDispatcherResult").
|
||||
defaultResultParam("location").build();
|
||||
PackageConfig packageConfig = new PackageConfig.Builder("package").
|
||||
defaultResultType("dispatcher").addResultTypeConfig(resultType).build();
|
||||
|
||||
DefaultResultMapBuilder builder = new DefaultResultMapBuilder(context, new ConventionsServiceImpl("/WEB-INF/component"), "dispatcher,velocity,freemarker");
|
||||
Map<String, ResultConfig> results = builder.build(NoAnnotationAction.class, null, "no-annotation", packageConfig);
|
||||
assertEquals(4, results.size());
|
||||
assertEquals("input", results.get("input").getName());
|
||||
assertEquals("error", results.get("error").getName());
|
||||
assertEquals("success", results.get("success").getName());
|
||||
assertEquals("foo", results.get("foo").getName());
|
||||
assertEquals(1, results.get("success").getParams().size());
|
||||
assertEquals("/WEB-INF/component/no-annotation.ftl", results.get("success").getParams().get("location"));
|
||||
assertEquals(1, results.get("input").getParams().size());
|
||||
assertEquals("/WEB-INF/component/no-annotation.ftl", results.get("input").getParams().get("location"));
|
||||
assertEquals(1, results.get("error").getParams().size());
|
||||
assertEquals("/WEB-INF/component/no-annotation.ftl", results.get("error").getParams().get("location"));
|
||||
assertEquals(1, results.get("foo").getParams().size());
|
||||
assertEquals("/WEB-INF/component/no-annotation-foo.ftl", results.get("foo").getParams().get("location"));
|
||||
}
|
||||
|
||||
private PackageConfig createPackageConfigBuilder(String namespace) {
|
||||
ResultTypeConfig resultType = new ResultTypeConfig.Builder("dispatcher", "org.apache.struts2.dispatcher.ServletDispatcherResult").
|
||||
addParam("key", "value").addParam("key1", "value1").defaultResultParam("location").build();
|
||||
|
||||
ResultTypeConfig redirect = new ResultTypeConfig.Builder("redirectAction",
|
||||
"org.apache.struts2.dispatcher.ServletActionRedirectResult").defaultResultParam("actionName").build();
|
||||
|
||||
ResultTypeConfig ftlResultType = new ResultTypeConfig.Builder("freemarker",
|
||||
"org.apache.struts2.views.freemarker.FreemarkerResult").defaultResultParam("location").build();
|
||||
|
||||
return new PackageConfig.Builder("package").
|
||||
namespace(namespace).
|
||||
defaultResultType("dispatcher").
|
||||
addResultTypeConfig(resultType).
|
||||
addResultTypeConfig(redirect).
|
||||
addResultTypeConfig(ftlResultType).build();
|
||||
}
|
||||
|
||||
private ServletContext mockServletContext(String resultPath) {
|
||||
ServletContext context = EasyMock.createStrictMock(ServletContext.class);
|
||||
|
||||
// Setup some mock jsps
|
||||
Set<String> resources = new HashSet<String>();
|
||||
resources.add(resultPath + "/namespace/action.jsp");
|
||||
resources.add(resultPath + "/namespace/action-success.jsp");
|
||||
resources.add(resultPath + "/namespace/action-failure.jsp");
|
||||
EasyMock.expect(context.getResourcePaths(resultPath + "/namespace/")).andReturn(resources);
|
||||
EasyMock.replay(context);
|
||||
return context;
|
||||
}
|
||||
|
||||
private void verify(ServletContext context, String resultPath, Map<String, ResultConfig> results,
|
||||
boolean redirect) {
|
||||
assertEquals(4, results.size());
|
||||
assertEquals("success", results.get("success").getName());
|
||||
assertEquals("input", results.get("input").getName());
|
||||
assertEquals("error", results.get("error").getName());
|
||||
assertEquals("failure", results.get("failure").getName());
|
||||
assertEquals(3, results.get("success").getParams().size());
|
||||
assertEquals(resultPath + "/namespace/action-success.jsp", results.get("success").getParams().get("location"));
|
||||
assertEquals("value", results.get("success").getParams().get("key"));
|
||||
assertEquals("value1", results.get("success").getParams().get("key1"));
|
||||
assertEquals(3, results.get("failure").getParams().size());
|
||||
assertEquals(resultPath + "/namespace/action-failure.jsp", results.get("failure").getParams().get("location"));
|
||||
assertEquals("value", results.get("failure").getParams().get("key"));
|
||||
assertEquals("value1", results.get("failure").getParams().get("key1"));
|
||||
|
||||
if (redirect) {
|
||||
assertEquals(1, results.get("input").getParams().size());
|
||||
assertEquals("foo.action", results.get("input").getParams().get("actionName"));
|
||||
} else {
|
||||
assertEquals(3, results.get("input").getParams().size());
|
||||
assertEquals(resultPath + "/namespace/action.jsp", results.get("input").getParams().get("location"));
|
||||
assertEquals("value", results.get("input").getParams().get("key"));
|
||||
assertEquals("value1", results.get("input").getParams().get("key1"));
|
||||
}
|
||||
|
||||
assertEquals(3, results.get("error").getParams().size());
|
||||
assertEquals(resultPath + "/namespace/action.jsp", results.get("error").getParams().get("location"));
|
||||
assertEquals("value", results.get("error").getParams().get("key"));
|
||||
assertEquals("value1", results.get("error").getParams().get("key1"));
|
||||
EasyMock.verify(context);
|
||||
}
|
||||
}
|
||||
+632
@@ -0,0 +1,632 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import static org.apache.struts2.convention.ReflectionTools.getAnnotation;
|
||||
import static org.easymock.EasyMock.checkOrder;
|
||||
import static org.easymock.EasyMock.createStrictMock;
|
||||
import static org.easymock.EasyMock.expect;
|
||||
import static org.easymock.EasyMock.verify;
|
||||
|
||||
import java.util.*;
|
||||
import java.net.MalformedURLException;
|
||||
import java.lang.reflect.Method;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.struts2.convention.actions.DefaultResultPathAction;
|
||||
import org.apache.struts2.convention.actions.NoAnnotationAction;
|
||||
import org.apache.struts2.convention.actions.Skip;
|
||||
import org.apache.struts2.convention.actions.chain.ChainedAction;
|
||||
import org.apache.struts2.convention.actions.action.ActionNameAction;
|
||||
import org.apache.struts2.convention.actions.action.ActionNamesAction;
|
||||
import org.apache.struts2.convention.actions.action.SingleActionNameAction;
|
||||
import org.apache.struts2.convention.actions.action.TestAction;
|
||||
import org.apache.struts2.convention.actions.action.TestExtends;
|
||||
import org.apache.struts2.convention.actions.defaultinterceptor.SingleActionNameAction2;
|
||||
import org.apache.struts2.convention.actions.exception.ExceptionsActionLevelAction;
|
||||
import org.apache.struts2.convention.actions.exception.ExceptionsMethodLevelAction;
|
||||
import org.apache.struts2.convention.actions.interceptor.ActionLevelInterceptor2Action;
|
||||
import org.apache.struts2.convention.actions.interceptor.ActionLevelInterceptor3Action;
|
||||
import org.apache.struts2.convention.actions.interceptor.ActionLevelInterceptorAction;
|
||||
import org.apache.struts2.convention.actions.interceptor.InterceptorsAction;
|
||||
import org.apache.struts2.convention.actions.namespace.ActionLevelNamespaceAction;
|
||||
import org.apache.struts2.convention.actions.namespace.ClassLevelNamespaceAction;
|
||||
import org.apache.struts2.convention.actions.namespace.PackageLevelNamespaceAction;
|
||||
import org.apache.struts2.convention.actions.namespace2.DefaultNamespaceAction;
|
||||
import org.apache.struts2.convention.actions.namespace3.ActionLevelNamespacesAction;
|
||||
import org.apache.struts2.convention.actions.namespace4.ActionAndPackageLevelNamespacesAction;
|
||||
import org.apache.struts2.convention.actions.params.ActionParamsMethodLevelAction;
|
||||
import org.apache.struts2.convention.actions.parentpackage.ClassLevelParentPackageAction;
|
||||
import org.apache.struts2.convention.actions.parentpackage.PackageLevelParentPackageAction;
|
||||
import org.apache.struts2.convention.actions.result.ActionLevelResultAction;
|
||||
import org.apache.struts2.convention.actions.result.ActionLevelResultsAction;
|
||||
import org.apache.struts2.convention.actions.result.ClassLevelResultAction;
|
||||
import org.apache.struts2.convention.actions.result.ClassLevelResultsAction;
|
||||
import org.apache.struts2.convention.actions.resultpath.ClassLevelResultPathAction;
|
||||
import org.apache.struts2.convention.actions.resultpath.PackageLevelResultPathAction;
|
||||
import org.apache.struts2.convention.actions.skip.Index;
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.Actions;
|
||||
import org.apache.struts2.dispatcher.ServletDispatcherResult;
|
||||
import org.easymock.EasyMock;
|
||||
|
||||
import com.opensymphony.xwork2.ObjectFactory;
|
||||
import com.opensymphony.xwork2.ActionContext;
|
||||
import com.opensymphony.xwork2.Result;
|
||||
import com.opensymphony.xwork2.ActionChainResult;
|
||||
import com.opensymphony.xwork2.util.reflection.ReflectionException;
|
||||
import com.opensymphony.xwork2.config.Configuration;
|
||||
import com.opensymphony.xwork2.config.entities.ActionConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ExceptionMappingConfig;
|
||||
import com.opensymphony.xwork2.config.entities.InterceptorConfig;
|
||||
import com.opensymphony.xwork2.config.entities.InterceptorMapping;
|
||||
import com.opensymphony.xwork2.config.entities.InterceptorStackConfig;
|
||||
import com.opensymphony.xwork2.config.entities.PackageConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultConfig;
|
||||
import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
|
||||
import com.opensymphony.xwork2.config.impl.DefaultConfiguration;
|
||||
import com.opensymphony.xwork2.inject.Container;
|
||||
import com.opensymphony.xwork2.inject.Scope.Strategy;
|
||||
import com.opensymphony.xwork2.ognl.OgnlReflectionProvider;
|
||||
import com.opensymphony.xwork2.ognl.OgnlUtil;
|
||||
|
||||
import javax.servlet.ServletContext;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test for the package based name builder.
|
||||
* </p>
|
||||
*/
|
||||
public class PackageBasedActionConfigBuilderTest extends TestCase {
|
||||
public void testActionPackages() throws MalformedURLException {
|
||||
run("org.apache.struts2.convention.actions", null, null);
|
||||
}
|
||||
|
||||
public void testPackageLocators() throws MalformedURLException {
|
||||
run(null, "actions,dontfind", null);
|
||||
}
|
||||
|
||||
private void run(String actionPackages, String packageLocators, String excludePackages) throws MalformedURLException {
|
||||
//setup interceptors
|
||||
List<InterceptorConfig> defaultInterceptors = new ArrayList<InterceptorConfig>();
|
||||
defaultInterceptors.add(makeInterceptorConfig("interceptor-1"));
|
||||
defaultInterceptors.add(makeInterceptorConfig("interceptor-2"));
|
||||
defaultInterceptors.add(makeInterceptorConfig("interceptor-3"));
|
||||
|
||||
//setup interceptor stacks
|
||||
List<InterceptorStackConfig> defaultInterceptorStacks = new ArrayList<InterceptorStackConfig>();
|
||||
InterceptorMapping interceptor1 = new InterceptorMapping("interceptor-1", new TestInterceptor());
|
||||
InterceptorMapping interceptor2 = new InterceptorMapping("interceptor-2", new TestInterceptor());
|
||||
defaultInterceptorStacks.add(makeInterceptorStackConfig("stack-1", interceptor1, interceptor2));
|
||||
|
||||
//setup results
|
||||
ResultTypeConfig[] defaultResults = new ResultTypeConfig[]{new ResultTypeConfig.Builder("dispatcher",
|
||||
ServletDispatcherResult.class.getName()).defaultResultParam("location").build(),
|
||||
new ResultTypeConfig.Builder("chain",
|
||||
ActionChainResult.class.getName()).defaultResultParam("actionName").build()};
|
||||
|
||||
PackageConfig strutsDefault = makePackageConfig("struts-default", null, null, "dispatcher",
|
||||
defaultResults, defaultInterceptors, defaultInterceptorStacks);
|
||||
|
||||
PackageConfig packageLevelParentPkg = makePackageConfig("package-level", null, null, null);
|
||||
PackageConfig classLevelParentPkg = makePackageConfig("class-level", null, null, null);
|
||||
|
||||
PackageConfig rootPkg = makePackageConfig("org.apache.struts2.convention.actions#struts-default#",
|
||||
"", strutsDefault, null);
|
||||
PackageConfig paramsPkg = makePackageConfig("org.apache.struts2.convention.actions.params#struts-default#/params",
|
||||
"/params", strutsDefault, null);
|
||||
PackageConfig defaultInterceptorPkg = makePackageConfig("org.apache.struts2.convention.actions.defaultinterceptor#struts-default#/defaultinterceptor",
|
||||
"/defaultinterceptor", strutsDefault, null);
|
||||
PackageConfig exceptionPkg = makePackageConfig("org.apache.struts2.convention.actions.exception#struts-default#/exception",
|
||||
"/exception", strutsDefault, null);
|
||||
PackageConfig actionPkg = makePackageConfig("org.apache.struts2.convention.actions.action#struts-default#/action",
|
||||
"/action", strutsDefault, null);
|
||||
PackageConfig idxPkg = makePackageConfig("org.apache.struts2.convention.actions.idx#struts-default#/idx",
|
||||
"/idx", strutsDefault, null);
|
||||
PackageConfig idx2Pkg = makePackageConfig("org.apache.struts2.convention.actions.idx.idx2#struts-default#/idx/idx2",
|
||||
"/idx/idx2", strutsDefault, null);
|
||||
PackageConfig interceptorRefsPkg = makePackageConfig("org.apache.struts2.convention.actions.interceptor#struts-default#/interceptor",
|
||||
"/interceptor", strutsDefault, null);
|
||||
PackageConfig packageLevelPkg = makePackageConfig("org.apache.struts2.convention.actions.parentpackage#package-level#/parentpackage",
|
||||
"/parentpackage", packageLevelParentPkg, null);
|
||||
PackageConfig differentPkg = makePackageConfig("org.apache.struts2.convention.actions.parentpackage#class-level#/parentpackage",
|
||||
"/parentpackage", classLevelParentPkg, null);
|
||||
PackageConfig pkgLevelNamespacePkg = makePackageConfig("org.apache.struts2.convention.actions.namespace#struts-default#/package-level",
|
||||
"/package-level", strutsDefault, null);
|
||||
PackageConfig classLevelNamespacePkg = makePackageConfig("org.apache.struts2.convention.actions.namespace#struts-default#/class-level",
|
||||
"/class-level", strutsDefault, null);
|
||||
PackageConfig actionLevelNamespacePkg = makePackageConfig("org.apache.struts2.convention.actions.namespace#struts-default#/action-level",
|
||||
"/action-level", strutsDefault, null);
|
||||
PackageConfig defaultNamespacePkg = makePackageConfig("org.apache.struts2.convention.actions.namespace2#struts-default#/namespace2",
|
||||
"/namespace2", strutsDefault, null);
|
||||
PackageConfig namespaces1Pkg = makePackageConfig("org.apache.struts2.convention.actions.namespace3#struts-default#/namespaces1",
|
||||
"/namespaces1", strutsDefault, null);
|
||||
PackageConfig namespaces2Pkg = makePackageConfig("org.apache.struts2.convention.actions.namespace3#struts-default#/namespaces2",
|
||||
"/namespaces2", strutsDefault, null);
|
||||
PackageConfig namespaces3Pkg = makePackageConfig("org.apache.struts2.convention.actions.namespace4#struts-default#/namespaces3",
|
||||
"/namespaces3", strutsDefault, null);
|
||||
PackageConfig namespaces4Pkg = makePackageConfig("org.apache.struts2.convention.actions.namespace4#struts-default#/namespaces4",
|
||||
"/namespaces4", strutsDefault, null);
|
||||
PackageConfig resultPkg = makePackageConfig("org.apache.struts2.convention.actions.result#struts-default#/result",
|
||||
"/result", strutsDefault, null);
|
||||
PackageConfig resultPathPkg = makePackageConfig("org.apache.struts2.convention.actions.resultpath#struts-default#/resultpath",
|
||||
"/resultpath", strutsDefault, null);
|
||||
PackageConfig skipPkg = makePackageConfig("org.apache.struts2.convention.actions.skip#struts-default#/skip",
|
||||
"/skip", strutsDefault, null);
|
||||
PackageConfig chainPkg = makePackageConfig("org.apache.struts2.convention.actions.chain#struts-default#/chain",
|
||||
"/chain", strutsDefault, null);
|
||||
|
||||
ResultMapBuilder resultMapBuilder = createStrictMock(ResultMapBuilder.class);
|
||||
checkOrder(resultMapBuilder, false);
|
||||
Map<String, ResultConfig> results = new HashMap<String, ResultConfig>();
|
||||
|
||||
/* org.apache.struts2.convention.actions.action */
|
||||
expect(resultMapBuilder.build(ActionNameAction.class, getAnnotation(ActionNameAction.class, "run1", Action.class), "action1", actionPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ActionNameAction.class, getAnnotation(ActionNameAction.class, "run2", Action.class), "action2", actionPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ActionNamesAction.class, getAnnotation(ActionNamesAction.class, "run", Actions.class).value()[0], "actions1", actionPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ActionNamesAction.class, getAnnotation(ActionNamesAction.class, "run", Actions.class).value()[1], "actions2", actionPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(SingleActionNameAction.class, getAnnotation(SingleActionNameAction.class, "run", Action.class), "action", actionPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(TestAction.class, null, "test", actionPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(TestExtends.class, null, "test-extends", actionPkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.idx */
|
||||
/* org.apache.struts2.convention.actions.idx.idx2 */
|
||||
expect(resultMapBuilder.build(org.apache.struts2.convention.actions.idx.Index.class, null, "index", idxPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(org.apache.struts2.convention.actions.idx.idx2.Index.class, null, "index", idx2Pkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.params */
|
||||
expect(resultMapBuilder.build(ActionParamsMethodLevelAction.class, getAnnotation(ActionParamsMethodLevelAction.class, "run1", Action.class), "actionParam1", paramsPkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.defaultinterceptor */
|
||||
expect(resultMapBuilder.build(SingleActionNameAction2.class, getAnnotation(SingleActionNameAction2.class, "execute", Action.class), "action345", defaultInterceptorPkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.exception */
|
||||
expect(resultMapBuilder.build(ExceptionsMethodLevelAction.class, getAnnotation(ExceptionsMethodLevelAction.class, "run1", Action.class), "exception1", exceptionPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ExceptionsActionLevelAction.class, getAnnotation(ExceptionsActionLevelAction.class, "execute", Action.class), "exceptions-action-level", exceptionPkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.interceptor */
|
||||
expect(resultMapBuilder.build(InterceptorsAction.class, getAnnotation(InterceptorsAction.class, "run1", Action.class), "action100", interceptorRefsPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(InterceptorsAction.class, getAnnotation(InterceptorsAction.class, "run2", Action.class), "action200", interceptorRefsPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(InterceptorsAction.class, getAnnotation(InterceptorsAction.class, "run3", Action.class), "action300", interceptorRefsPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(InterceptorsAction.class, getAnnotation(InterceptorsAction.class, "run4", Action.class), "action400", interceptorRefsPkg)).andReturn(results);
|
||||
|
||||
expect(resultMapBuilder.build(ActionLevelInterceptorAction.class, getAnnotation(ActionLevelInterceptorAction.class, "run1", Action.class), "action500", interceptorRefsPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ActionLevelInterceptorAction.class, getAnnotation(ActionLevelInterceptorAction.class, "run2", Action.class), "action600", interceptorRefsPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ActionLevelInterceptorAction.class, getAnnotation(ActionLevelInterceptorAction.class, "run3", Action.class), "action700", interceptorRefsPkg)).andReturn(results);
|
||||
|
||||
expect(resultMapBuilder.build(ActionLevelInterceptor2Action.class, getAnnotation(ActionLevelInterceptor2Action.class, "run1", Action.class), "action800", interceptorRefsPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ActionLevelInterceptor3Action.class, getAnnotation(ActionLevelInterceptor3Action.class, "run1", Action.class), "action900", interceptorRefsPkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.namespace */
|
||||
expect(resultMapBuilder.build(ActionLevelNamespaceAction.class, getAnnotation(ActionLevelNamespaceAction.class, "execute", Action.class), "action", actionLevelNamespacePkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ClassLevelNamespaceAction.class, null, "class-level-namespace", classLevelNamespacePkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(PackageLevelNamespaceAction.class, null, "package-level-namespace", pkgLevelNamespacePkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.namespace2 */
|
||||
expect(resultMapBuilder.build(DefaultNamespaceAction.class, null, "default-namespace", defaultNamespacePkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.namespace3 */
|
||||
expect(resultMapBuilder.build(ActionLevelNamespacesAction.class, null, "action-level-namespaces", namespaces1Pkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ActionLevelNamespacesAction.class, null, "action-level-namespaces", namespaces2Pkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.namespace4 */
|
||||
expect(resultMapBuilder.build(ActionAndPackageLevelNamespacesAction.class, null, "action-and-package-level-namespaces", namespaces3Pkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ActionAndPackageLevelNamespacesAction.class, null, "action-and-package-level-namespaces", namespaces4Pkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.parentpackage */
|
||||
expect(resultMapBuilder.build(PackageLevelParentPackageAction.class, null, "package-level-parent-package", packageLevelPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ClassLevelParentPackageAction.class, null, "class-level-parent-package", differentPkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.result */
|
||||
expect(resultMapBuilder.build(ClassLevelResultAction.class, null, "class-level-result", resultPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ClassLevelResultsAction.class, null, "class-level-results", resultPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ActionLevelResultAction.class, getAnnotation(ActionLevelResultAction.class, "execute", Action.class), "action-level-result", resultPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ActionLevelResultsAction.class, getAnnotation(ActionLevelResultsAction.class, "execute", Action.class), "action-level-results", resultPkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.resultpath */
|
||||
expect(resultMapBuilder.build(ClassLevelResultPathAction.class, null, "class-level-result-path", resultPathPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(PackageLevelResultPathAction.class, null, "package-level-result-path", resultPathPkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions */
|
||||
expect(resultMapBuilder.build(NoAnnotationAction.class, null, "no-annotation", rootPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(DefaultResultPathAction.class, null, "default-result-path", rootPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(Skip.class, null, "skip", rootPkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.skip */
|
||||
expect(resultMapBuilder.build(Index.class, null, "index", skipPkg)).andReturn(results);
|
||||
|
||||
/* org.apache.struts2.convention.actions.chain */
|
||||
expect(resultMapBuilder.build(ChainedAction.class, getAnnotation(ChainedAction.class, "foo", Action.class), "foo", chainPkg)).andReturn(results);
|
||||
expect(resultMapBuilder.build(ChainedAction.class, getAnnotation(ChainedAction.class, "bar", Action.class), "foo-bar", chainPkg)).andReturn(results);
|
||||
|
||||
EasyMock.replay(resultMapBuilder);
|
||||
|
||||
Configuration configuration = new DefaultConfiguration() {
|
||||
|
||||
@Override
|
||||
public Container getContainer() {
|
||||
return new DummyContainer();
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
configuration.addPackageConfig("struts-default", strutsDefault);
|
||||
configuration.addPackageConfig("package-level", packageLevelParentPkg);
|
||||
configuration.addPackageConfig("class-level", classLevelParentPkg);
|
||||
|
||||
ActionNameBuilder actionNameBuilder = new SEOActionNameBuilder("true", "-");
|
||||
ObjectFactory of = new ObjectFactory();
|
||||
DefaultInterceptorMapBuilder interceptorBuilder = new DefaultInterceptorMapBuilder();
|
||||
interceptorBuilder.setConfiguration(configuration);
|
||||
PackageBasedActionConfigBuilder builder = new PackageBasedActionConfigBuilder(configuration,
|
||||
actionNameBuilder, resultMapBuilder, interceptorBuilder ,of, "false", "struts-default");
|
||||
builder.setDisableJarScanning("true");
|
||||
if (actionPackages != null) {
|
||||
builder.setActionPackages(actionPackages);
|
||||
}
|
||||
if (packageLocators != null) {
|
||||
builder.setPackageLocators(packageLocators);
|
||||
}
|
||||
if (excludePackages != null) {
|
||||
builder.setExcludePackages(excludePackages);
|
||||
}
|
||||
builder.setPackageLocatorsBase("org.apache.struts2.convention.actions");
|
||||
builder.buildActionConfigs();
|
||||
verify(resultMapBuilder);
|
||||
|
||||
/* org.apache.struts2.convention.actions.action */
|
||||
PackageConfig pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.action#struts-default#/action");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(7, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "action1", ActionNameAction.class, "run1", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "action2", ActionNameAction.class, "run2", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "actions1", ActionNamesAction.class, "run", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "actions2", ActionNamesAction.class, "run", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "action", SingleActionNameAction.class, "run", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "test", TestAction.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "test-extends", TestExtends.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.namespace3 */
|
||||
//action on namespace1 (action level)
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.namespace3#struts-default#/namespaces1");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "action-level-namespaces", ActionLevelNamespacesAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
//action on namespace2 (action level)
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.namespace3#struts-default#/namespaces2");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "action-level-namespaces", ActionLevelNamespacesAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.namespace4 */
|
||||
//action on namespace3 (action level)
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.namespace4#struts-default#/namespaces3");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "action-and-package-level-namespaces", ActionAndPackageLevelNamespacesAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
//action on namespace4 (package level)
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.namespace4#struts-default#/namespaces4");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "action-and-package-level-namespaces", ActionAndPackageLevelNamespacesAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
|
||||
|
||||
/* org.apache.struts2.convention.actions.params */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.params#struts-default#/params");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
ActionConfig ac = pkgConfig.getAllActionConfigs().get("actionParam1");
|
||||
assertNotNull(ac);
|
||||
Map<String, String> params = ac.getParams();
|
||||
assertNotNull(params);
|
||||
assertEquals(2, params.size());
|
||||
assertEquals("val1", params.get("param1"));
|
||||
assertEquals("val2", params.get("param2"));
|
||||
|
||||
/* org.apache.struts2.convention.actions.params */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.exception#struts-default#/exception");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(2, pkgConfig.getActionConfigs().size());
|
||||
|
||||
ac = pkgConfig.getAllActionConfigs().get("exception1");
|
||||
assertNotNull(ac);
|
||||
List<ExceptionMappingConfig> exceptions = ac.getExceptionMappings();
|
||||
assertNotNull(exceptions);
|
||||
assertEquals(2, exceptions.size());
|
||||
ExceptionMappingConfig exception = exceptions.get(0);
|
||||
assertEquals("NPE1", exception.getExceptionClassName());
|
||||
assertEquals("success", exception.getResult());
|
||||
exception = exceptions.get(1);
|
||||
assertEquals("NPE2", exception.getExceptionClassName());
|
||||
assertEquals("success", exception.getResult());
|
||||
params = exception.getParams();
|
||||
assertNotNull(params);
|
||||
assertEquals(1, params.size());
|
||||
assertEquals("val1", params.get("param1"));
|
||||
|
||||
ac = pkgConfig.getAllActionConfigs().get("exceptions-action-level");
|
||||
assertNotNull(ac);
|
||||
exceptions = ac.getExceptionMappings();
|
||||
assertNotNull(exceptions);
|
||||
assertEquals(2, exceptions.size());
|
||||
exception = exceptions.get(0);
|
||||
assertEquals("NPE1", exception.getExceptionClassName());
|
||||
assertEquals("success", exception.getResult());
|
||||
exception = exceptions.get(1);
|
||||
assertEquals("NPE2", exception.getExceptionClassName());
|
||||
assertEquals("success", exception.getResult());
|
||||
params = exception.getParams();
|
||||
assertNotNull(params);
|
||||
assertEquals(1, params.size());
|
||||
assertEquals("val1", params.get("param1"));
|
||||
|
||||
/* org.apache.struts2.convention.actions.idx */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.idx#struts-default#/idx");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(3, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "", org.apache.struts2.convention.actions.idx.Index.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "index", org.apache.struts2.convention.actions.idx.Index.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "idx2", org.apache.struts2.convention.actions.idx.idx2.Index.class, "execute",
|
||||
"org.apache.struts2.convention.actions.idx.idx2#struts-default#/idx/idx2");
|
||||
|
||||
/* org.apache.struts2.convention.actions.defaultinterceptor */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.defaultinterceptor#struts-default#/defaultinterceptor");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals("validationWorkflowStack", pkgConfig.getDefaultInterceptorRef());
|
||||
|
||||
/* org.apache.struts2.convention.actions.idx.idx2 */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.idx.idx2#struts-default#/idx/idx2");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(2, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "", org.apache.struts2.convention.actions.idx.idx2.Index.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "index", org.apache.struts2.convention.actions.idx.idx2.Index.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.namespace action level */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.namespace#struts-default#/action-level");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "action", ActionLevelNamespaceAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.namespace class level */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.namespace#struts-default#/class-level");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "class-level-namespace", ClassLevelNamespaceAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.namespace package level */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.namespace#struts-default#/package-level");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "package-level-namespace", PackageLevelNamespaceAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.namespace2 */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.namespace2#struts-default#/namespace2");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "default-namespace", DefaultNamespaceAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.parentpackage class level */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.parentpackage#class-level#/parentpackage");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "class-level-parent-package", ClassLevelParentPackageAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.parentpackage package level */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.parentpackage#package-level#/parentpackage");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(1, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "package-level-parent-package", PackageLevelParentPackageAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.result */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.result#struts-default#/result");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(4, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "class-level-result", ClassLevelResultAction.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "class-level-results", ClassLevelResultsAction.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "action-level-result", ActionLevelResultAction.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "action-level-results", ActionLevelResultsAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.resultpath */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.resultpath#struts-default#/resultpath");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(2, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "class-level-result-path", ClassLevelResultPathAction.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "package-level-result-path", PackageLevelResultPathAction.class, "execute", pkgConfig.getName());
|
||||
|
||||
/* org.apache.struts2.convention.actions.interceptorRefs */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.interceptor#struts-default#/interceptor");
|
||||
assertNotNull(pkgConfig);
|
||||
assertEquals(9, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfigInterceptors(pkgConfig, "action100", "interceptor-1");
|
||||
verifyActionConfigInterceptors(pkgConfig, "action200", "interceptor-1", "interceptor-2");
|
||||
verifyActionConfigInterceptors(pkgConfig, "action300", "interceptor-1", "interceptor-2");
|
||||
verifyActionConfigInterceptors(pkgConfig, "action400", "interceptor-1", "interceptor-1", "interceptor-2");
|
||||
|
||||
// Interceptors at class level
|
||||
verifyActionConfigInterceptors(pkgConfig, "action500", "interceptor-1");
|
||||
verifyActionConfigInterceptors(pkgConfig, "action600", "interceptor-1", "interceptor-2");
|
||||
verifyActionConfigInterceptors(pkgConfig, "action700", "interceptor-1", "interceptor-1", "interceptor-2");
|
||||
|
||||
//multiple interceptor at class level
|
||||
verifyActionConfigInterceptors(pkgConfig, "action800", "interceptor-1", "interceptor-2");
|
||||
verifyActionConfigInterceptors(pkgConfig, "action900", "interceptor-1", "interceptor-1", "interceptor-2");
|
||||
|
||||
/* org.apache.struts2.convention.actions */
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions#struts-default#");
|
||||
assertNotNull(pkgConfig);
|
||||
System.out.println("actions " + pkgConfig.getActionConfigs());
|
||||
assertEquals(4, pkgConfig.getActionConfigs().size());
|
||||
verifyActionConfig(pkgConfig, "no-annotation", NoAnnotationAction.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "default-result-path", DefaultResultPathAction.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "skip", Skip.class, "execute", pkgConfig.getName());
|
||||
verifyActionConfig(pkgConfig, "idx", org.apache.struts2.convention.actions.idx.Index.class, "execute",
|
||||
"org.apache.struts2.convention.actions.idx#struts-default#/idx");
|
||||
|
||||
//test unknown handler automatic chaining
|
||||
pkgConfig = configuration.getPackageConfig("org.apache.struts2.convention.actions.chain#struts-default#/chain");
|
||||
ServletContext context = EasyMock.createNiceMock(ServletContext.class);
|
||||
EasyMock.replay(context);
|
||||
|
||||
ObjectFactory workingFactory = configuration.getContainer().getInstance(ObjectFactory.class);
|
||||
ConventionUnknownHandler uh = new ConventionUnknownHandler(configuration, workingFactory, context, resultMapBuilder, new ConventionsServiceImpl(""), "struts-default", null, "-");
|
||||
ActionContext actionContext = new ActionContext(Collections.EMPTY_MAP);
|
||||
|
||||
Result result = uh.handleUnknownResult(actionContext, "foo", pkgConfig.getActionConfigs().get("foo"), "bar");
|
||||
assertNotNull(result);
|
||||
assertTrue(result instanceof ActionChainResult);
|
||||
ActionChainResult chainResult = (ActionChainResult) result;
|
||||
ActionChainResult chainResultToCompare = new ActionChainResult("/chain", "foo-bar", "bar");
|
||||
}
|
||||
|
||||
private void verifyActionConfig(PackageConfig pkgConfig, String actionName, Class<?> actionClass,
|
||||
String methodName, String packageName) {
|
||||
ActionConfig ac = pkgConfig.getAllActionConfigs().get(actionName);
|
||||
assertNotNull(ac);
|
||||
assertEquals(actionClass.getName(), ac.getClassName());
|
||||
assertEquals(methodName, ac.getMethodName());
|
||||
assertEquals(packageName, ac.getPackageName());
|
||||
}
|
||||
|
||||
private void verifyActionConfigInterceptors(PackageConfig pkgConfig, String actionName, String... refs) {
|
||||
ActionConfig ac = pkgConfig.getAllActionConfigs().get(actionName);
|
||||
assertNotNull(ac);
|
||||
List<InterceptorMapping> interceptorMappings = ac.getInterceptors();
|
||||
for (int i = 0; i < interceptorMappings.size(); i++) {
|
||||
InterceptorMapping interceptorMapping = interceptorMappings.get(i);
|
||||
assertEquals(refs[i], interceptorMapping.getName());
|
||||
}
|
||||
}
|
||||
|
||||
private PackageConfig makePackageConfig(String name, String namespace, PackageConfig parent,
|
||||
String defaultResultType, ResultTypeConfig... results) {
|
||||
return makePackageConfig(name, namespace, parent, defaultResultType, results, null, null);
|
||||
}
|
||||
|
||||
private PackageConfig makePackageConfig(String name, String namespace, PackageConfig parent,
|
||||
String defaultResultType, ResultTypeConfig[] results, List<InterceptorConfig> interceptors,
|
||||
List<InterceptorStackConfig> interceptorStacks) {
|
||||
PackageConfig.Builder builder = new PackageConfig.Builder(name);
|
||||
if (namespace != null) {
|
||||
builder.namespace(namespace);
|
||||
}
|
||||
if (parent != null) {
|
||||
builder.addParent(parent);
|
||||
}
|
||||
if (defaultResultType != null) {
|
||||
builder.defaultResultType(defaultResultType);
|
||||
}
|
||||
if (results != null) {
|
||||
for (ResultTypeConfig result : results) {
|
||||
builder.addResultTypeConfig(result);
|
||||
}
|
||||
}
|
||||
if (interceptors != null) {
|
||||
for (InterceptorConfig ref : interceptors) {
|
||||
builder.addInterceptorConfig(ref);
|
||||
}
|
||||
}
|
||||
if (interceptorStacks != null) {
|
||||
for (InterceptorStackConfig ref : interceptorStacks) {
|
||||
builder.addInterceptorStackConfig(ref);
|
||||
}
|
||||
}
|
||||
|
||||
return new MyPackageConfig(builder.build());
|
||||
}
|
||||
|
||||
private InterceptorConfig makeInterceptorConfig(String name) {
|
||||
InterceptorConfig.Builder builder = new InterceptorConfig.Builder(name, "org.apache.struts2.convention.TestInterceptor");
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private InterceptorStackConfig makeInterceptorStackConfig(String name, InterceptorMapping... interceptors) {
|
||||
InterceptorStackConfig.Builder builder = new InterceptorStackConfig.Builder(name);
|
||||
for (InterceptorMapping interceptor : interceptors)
|
||||
builder.addInterceptor(interceptor);
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
public class MyPackageConfig extends PackageConfig {
|
||||
protected MyPackageConfig(PackageConfig packageConfig) {
|
||||
super(packageConfig);
|
||||
}
|
||||
|
||||
public boolean equals(Object obj) {
|
||||
PackageConfig other = (PackageConfig) obj;
|
||||
return getName().equals(other.getName()) && getNamespace().equals(other.getNamespace()) &&
|
||||
getParents().get(0) == other.getParents().get(0) && getParents().size() == other.getParents().size();
|
||||
}
|
||||
}
|
||||
|
||||
public class DummyContainer implements Container {
|
||||
|
||||
public <T> T getInstance(Class<T> type) {
|
||||
try {
|
||||
T obj = type.newInstance();
|
||||
if (obj instanceof ObjectFactory) {
|
||||
((ObjectFactory)obj).setReflectionProvider(new OgnlReflectionProvider() {
|
||||
|
||||
@Override
|
||||
public void setProperties(Map<String, String> properties, Object o) {
|
||||
}
|
||||
|
||||
public void setProperties(Map<String, String> properties, Object o, Map<String, Object> context, boolean throwPropertyExceptions) throws ReflectionException {
|
||||
if (o instanceof ActionChainResult) {
|
||||
((ActionChainResult)o).setActionName(properties.get("actionName"));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
return obj;
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public <T> T getInstance(Class<T> type, String name) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<String> getInstanceNames(Class<?> type) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void inject(Object o) {
|
||||
|
||||
}
|
||||
|
||||
public <T> T inject(Class<T> implementation) {
|
||||
return null;
|
||||
}
|
||||
|
||||
public void removeScopeStrategy() {
|
||||
|
||||
}
|
||||
|
||||
public void setScopeStrategy(Strategy scopeStrategy) {
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This tests the reflection tools.
|
||||
* </p>
|
||||
*/
|
||||
public class ReflectionToolsTest extends TestCase {
|
||||
public void testContainsMethod() {
|
||||
assertTrue(ReflectionTools.containsMethod(this.getClass(), "testContainsMethod"));
|
||||
assertFalse(ReflectionTools.containsMethod(this.getClass(), "badMethod"));
|
||||
}
|
||||
}
|
||||
+46
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class tests the SEO name builder.
|
||||
* </p>
|
||||
*/
|
||||
public class SEOActionNameBuilderTest extends TestCase {
|
||||
public void testBuild() throws Exception {
|
||||
SEOActionNameBuilder builder = new SEOActionNameBuilder("true", "_");
|
||||
assertEquals("foo", builder.build("Foo"));
|
||||
assertEquals("foo", builder.build("FooAction"));
|
||||
assertEquals("foo_bar", builder.build("FooBarAction"));
|
||||
assertEquals("foo_bar_baz", builder.build("FooBarBazAction"));
|
||||
}
|
||||
|
||||
public void testDash() throws Exception {
|
||||
SEOActionNameBuilder builder = new SEOActionNameBuilder("true", "-");
|
||||
assertEquals("foo", builder.build("Foo"));
|
||||
assertEquals("foo", builder.build("FooAction"));
|
||||
assertEquals("foo-bar", builder.build("FooBarAction"));
|
||||
assertEquals("foo-bar-baz", builder.build("FooBarBazAction"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class tests the string tools.
|
||||
* </p>
|
||||
*/
|
||||
public class StringToolsTest extends TestCase {
|
||||
public void testEmpty() {
|
||||
assertTrue(StringTools.isTrimmedEmpty(null));
|
||||
assertTrue(StringTools.isTrimmedEmpty(""));
|
||||
assertTrue(StringTools.isTrimmedEmpty(" "));
|
||||
assertFalse(StringTools.isTrimmedEmpty("f"));
|
||||
assertFalse(StringTools.isTrimmedEmpty(" f "));
|
||||
}
|
||||
|
||||
public void testLastToken() {
|
||||
assertEquals("bar", StringTools.lastToken("/foo/bar", "/"));
|
||||
assertEquals("baz", StringTools.lastToken("/foo/bar/baz", "/"));
|
||||
assertEquals("baz", StringTools.lastToken("baz", "/"));
|
||||
}
|
||||
|
||||
public void testUpToLastToken() {
|
||||
assertEquals("/foo", StringTools.upToLastToken("/foo/bar", "/"));
|
||||
assertEquals("/foo/bar", StringTools.upToLastToken("/foo/bar/baz", "/"));
|
||||
assertEquals("", StringTools.upToLastToken("/foo", "/"));
|
||||
assertEquals("", StringTools.upToLastToken("foo", "/"));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
package org.apache.struts2.convention;
|
||||
|
||||
import com.opensymphony.xwork2.ActionInvocation;
|
||||
import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
|
||||
|
||||
public class TestInterceptor extends AbstractInterceptor {
|
||||
private String string1;
|
||||
|
||||
@Override
|
||||
public String intercept(ActionInvocation invocation) throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getString1() {
|
||||
return string1;
|
||||
}
|
||||
|
||||
public void setString1(String string1) {
|
||||
this.string1 = string1;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class is a test action with the default result path.
|
||||
* </p>
|
||||
*/
|
||||
public class DefaultResultPathAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a struts action with no annotations.
|
||||
* </p>
|
||||
*/
|
||||
public class NoAnnotationAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions;
|
||||
|
||||
import com.opensymphony.xwork2.Action;
|
||||
|
||||
public class Skip implements Action {
|
||||
public String execute() throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+40
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.action;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action.
|
||||
* </p>
|
||||
*/
|
||||
public class ActionNameAction {
|
||||
@Action("action1")
|
||||
public String run1() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Action("action2")
|
||||
public String run2() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+39
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.action;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.Actions;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class is a test action.
|
||||
* </p>
|
||||
*/
|
||||
public class ActionNamesAction {
|
||||
@Actions({
|
||||
@Action("actions1"),
|
||||
@Action("actions2")
|
||||
})
|
||||
public String run() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.action;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action.
|
||||
* </p>
|
||||
*/
|
||||
public class SingleActionNameAction {
|
||||
@Action("action")
|
||||
public String run() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.action;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action.
|
||||
* </p>
|
||||
*/
|
||||
public class TestAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+27
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.action;
|
||||
|
||||
import com.opensymphony.xwork2.ActionSupport;
|
||||
|
||||
public abstract class TestBase extends ActionSupport {
|
||||
|
||||
}
|
||||
+25
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.action;
|
||||
|
||||
public class TestExtends extends TestBase {
|
||||
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id: ActionNamesAction.java 655902 2008-05-13 15:15:12Z bpontarelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.convention.actions.chain;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
|
||||
public class ChainedAction {
|
||||
@Action("foo")
|
||||
public String foo() {
|
||||
return "bar";
|
||||
}
|
||||
|
||||
@Action("foo-bar")
|
||||
public String bar() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.defaultinterceptor;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action.
|
||||
* </p>
|
||||
*/
|
||||
public class SingleActionNameAction2 implements com.opensymphony.xwork2.Action{
|
||||
@Action("action345")
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
@org.apache.struts2.convention.annotation.DefaultInterceptorRef("validationWorkflowStack")
|
||||
package org.apache.struts2.convention.actions.defaultinterceptor;
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.exception;
|
||||
|
||||
import org.apache.struts2.convention.annotation.ExceptionMapping;
|
||||
import org.apache.struts2.convention.annotation.ExceptionMappings;
|
||||
|
||||
@ExceptionMappings({
|
||||
@ExceptionMapping(exception = "NPE1", result = "success"),
|
||||
@ExceptionMapping(exception = "NPE2", result = "success", params = {"param1", "val1"})
|
||||
})
|
||||
public class ExceptionsActionLevelAction {
|
||||
|
||||
public String execute() throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.exception;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.ExceptionMapping;
|
||||
|
||||
public class ExceptionsMethodLevelAction {
|
||||
|
||||
@Action(value = "exception1", exceptionMappings = {
|
||||
@ExceptionMapping(exception = "NPE1", result = "success"),
|
||||
@ExceptionMapping(exception = "NPE2", result = "success", params = {"param1", "val1"})
|
||||
})
|
||||
public String run1() throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.idx;
|
||||
|
||||
import com.opensymphony.xwork2.Action;
|
||||
|
||||
public class Index implements Action {
|
||||
public String execute() throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.idx.idx2;
|
||||
|
||||
import com.opensymphony.xwork2.Action;
|
||||
|
||||
public class Index implements Action {
|
||||
public String execute() throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* $Id: ActionLevelResultAction.java 655902 2008-05-13 15:15:12Z bpontarelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.convention.actions.interceptor;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.InterceptorRef;
|
||||
import org.apache.struts2.convention.annotation.InterceptorRefs;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action with 2 interceptors at the action level.
|
||||
* </p>
|
||||
*/
|
||||
@InterceptorRefs({
|
||||
@InterceptorRef("interceptor-1"),
|
||||
@InterceptorRef("interceptor-2")
|
||||
})
|
||||
public class ActionLevelInterceptor2Action {
|
||||
|
||||
@Action(value = "action800")
|
||||
public String run1() throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+42
@@ -0,0 +1,42 @@
|
||||
/*
|
||||
* $Id: ActionLevelResultAction.java 655902 2008-05-13 15:15:12Z bpontarelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.convention.actions.interceptor;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.InterceptorRef;
|
||||
import org.apache.struts2.convention.annotation.InterceptorRefs;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action with 1 interceptor and 1 stack at the action level.
|
||||
* </p>
|
||||
*/
|
||||
@InterceptorRefs({
|
||||
@InterceptorRef("interceptor-1"),
|
||||
@InterceptorRef("stack-1")
|
||||
})
|
||||
public class ActionLevelInterceptor3Action {
|
||||
|
||||
@Action(value = "action900")
|
||||
public String run1() throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+48
@@ -0,0 +1,48 @@
|
||||
/*
|
||||
* $Id: ActionLevelResultAction.java 655902 2008-05-13 15:15:12Z bpontarelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.convention.actions.interceptor;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.InterceptorRef;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action with one interceptor at the action level.
|
||||
* </p>
|
||||
*/
|
||||
@InterceptorRef("interceptor-1")
|
||||
public class ActionLevelInterceptorAction {
|
||||
|
||||
@Action(value = "action500")
|
||||
public String run1() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Action(value = "action600", interceptorRefs = @InterceptorRef("interceptor-2"))
|
||||
public String run2() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Action(value = "action700", interceptorRefs = @InterceptorRef("stack-1"))
|
||||
public String run3() throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+51
@@ -0,0 +1,51 @@
|
||||
/*
|
||||
* $Id: ActionLevelResultAction.java 655902 2008-05-13 15:15:12Z bpontarelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.convention.actions.interceptor;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.InterceptorRef;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action with multiple interceptors.
|
||||
* </p>
|
||||
*/
|
||||
public class InterceptorsAction {
|
||||
@Action(value = "action100", interceptorRefs = @InterceptorRef("interceptor-1"))
|
||||
public String run1() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Action(value = "action200", interceptorRefs = @InterceptorRef("stack-1"))
|
||||
public String run2() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Action(value = "action300", interceptorRefs = {@InterceptorRef("interceptor-1"), @InterceptorRef("interceptor-2")})
|
||||
public String run3() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Action(value = "action400", interceptorRefs = {@InterceptorRef("interceptor-1"), @InterceptorRef("stack-1")})
|
||||
public String run4() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.namespace;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class uses the action level annotation override.
|
||||
* </p>
|
||||
*/
|
||||
public class ActionLevelNamespaceAction {
|
||||
@Action("/action-level/action")
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.namespace;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Namespace;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class uses the class level annotation override.
|
||||
* </p>
|
||||
*/
|
||||
@Namespace("/class-level")
|
||||
public class ClassLevelNamespaceAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.namespace;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class uses the package level annotation.
|
||||
* </p>
|
||||
*/
|
||||
public class PackageLevelNamespaceAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
@org.apache.struts2.convention.annotation.Namespace("/package-level")
|
||||
package org.apache.struts2.convention.actions.namespace;
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.namespace2;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class uses the package level annotation.
|
||||
* </p>
|
||||
*/
|
||||
public class DefaultNamespaceAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+34
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.namespace3;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Namespace;
|
||||
import org.apache.struts2.convention.annotation.Namespaces;
|
||||
|
||||
@Namespaces({
|
||||
@Namespace("/namespaces1"),
|
||||
@Namespace("/namespaces2")
|
||||
})
|
||||
public class ActionLevelNamespacesAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.namespace4;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Namespace;
|
||||
import org.apache.struts2.convention.annotation.Namespaces;
|
||||
|
||||
@Namespaces({
|
||||
@Namespace("/namespaces3")
|
||||
})
|
||||
public class ActionAndPackageLevelNamespacesAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+22
@@ -0,0 +1,22 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
@org.apache.struts2.convention.annotation.Namespace("/namespaces4")
|
||||
package org.apache.struts2.convention.actions.namespace4;
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.params;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
|
||||
public class ActionParamsMethodLevelAction {
|
||||
private String param1;
|
||||
private String param2;
|
||||
|
||||
@Action(value = "actionParam1", params = {"param1", "val1", "param2", "val2"})
|
||||
public String run1() throws Exception {
|
||||
return null;
|
||||
}
|
||||
|
||||
public String getParam1() {
|
||||
return param1;
|
||||
}
|
||||
|
||||
public void setParam1(String param1) {
|
||||
this.param1 = param1;
|
||||
}
|
||||
|
||||
public String getParam2() {
|
||||
return param2;
|
||||
}
|
||||
|
||||
public void setParam2(String param2) {
|
||||
this.param2 = param2;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.parentpackage;
|
||||
|
||||
import org.apache.struts2.convention.annotation.ParentPackage;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a parent package usage action.
|
||||
* </p>
|
||||
*/
|
||||
@ParentPackage("class-level")
|
||||
public class ClassLevelParentPackageAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.parentpackage;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a parent package usage action.
|
||||
* </p>
|
||||
*/
|
||||
public class PackageLevelParentPackageAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
@org.apache.struts2.convention.annotation.ParentPackage("package-level")
|
||||
package org.apache.struts2.convention.actions.parentpackage;
|
||||
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.result;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.Result;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action with multiple results.
|
||||
* </p>
|
||||
*/
|
||||
public class ActionLevelResultAction {
|
||||
@Action(results = {
|
||||
@Result(name="success", location="/WEB-INF/location/namespace/action-success.jsp")
|
||||
})
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.result;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
import org.apache.struts2.convention.annotation.Result;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action with multiple results.
|
||||
* </p>
|
||||
*/
|
||||
public class ActionLevelResultsAction {
|
||||
@Action(results = {
|
||||
@Result(name="error", location="error.jsp"),
|
||||
@Result(name="input", location="foo.action", type="redirectAction"),
|
||||
@Result(name="success", location="/WEB-INF/location/namespace/action-success.jsp"),
|
||||
@Result(name="failure", location="/WEB-INF/location/namespace/action-failure.jsp")
|
||||
})
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.result;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Result;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action with multiple results.
|
||||
* </p>
|
||||
*/
|
||||
@Result(name="error", location="error.jsp", params={"key", "value", "key1", "value1"})
|
||||
public class ClassLevelResultAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+41
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.result;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Result;
|
||||
import org.apache.struts2.convention.annotation.Results;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This is a test action with multiple results.
|
||||
* </p>
|
||||
*/
|
||||
@Results({
|
||||
@Result(name="error", location="error.jsp", params={"key", "ann-value", "key1", "ann-value1"}),
|
||||
@Result(name="input", location="foo.action", type="redirectAction"),
|
||||
@Result(name="success", location="/WEB-INF/location/namespace/action-success.jsp"),
|
||||
@Result(name="failure", location="/WEB-INF/location/namespace/action-failure.jsp")
|
||||
})
|
||||
public class ClassLevelResultsAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+35
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.resultpath;
|
||||
|
||||
import org.apache.struts2.convention.annotation.ResultPath;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class is a test action with the default result path.
|
||||
* </p>
|
||||
*/
|
||||
@ResultPath("/class-level")
|
||||
public class ClassLevelResultPathAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+32
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.resultpath;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class is a test action with the default result path.
|
||||
* </p>
|
||||
*/
|
||||
public class PackageLevelResultPathAction {
|
||||
public String execute() {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+23
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
@org.apache.struts2.convention.annotation.ResultPath("/package-level")
|
||||
package org.apache.struts2.convention.actions.resultpath;
|
||||
|
||||
+29
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.actions.skip;
|
||||
|
||||
import com.opensymphony.xwork2.Action;
|
||||
|
||||
public class Index implements Action {
|
||||
public String execute() throws Exception {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+45
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* $Id$
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.apache.struts2.convention.annotation;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.apache.struts2.convention.actions.namespace.PackageLevelNamespaceAction;
|
||||
import org.apache.struts2.convention.actions.resultpath.ClassLevelResultPathAction;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* This class tests the annotation tools.
|
||||
* </p>
|
||||
*/
|
||||
public class AnnotationToolsTest extends TestCase {
|
||||
public void testFindAnnotationOnClass() {
|
||||
ResultPath rl = AnnotationTools.findAnnotation(ClassLevelResultPathAction.class, ResultPath.class);
|
||||
assertNotNull(rl);
|
||||
assertEquals("/class-level", rl.value());
|
||||
}
|
||||
|
||||
public void testFindAnnotationOnPackage() {
|
||||
Namespace ns = AnnotationTools.findAnnotation(PackageLevelNamespaceAction.class, Namespace.class);
|
||||
assertNotNull(ns);
|
||||
assertEquals("/package-level", ns.value());
|
||||
}
|
||||
}
|
||||
+31
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* $Id: ActionNamesAction.java 655902 2008-05-13 15:15:12Z bpontarelli $
|
||||
*
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS 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.convention.dontfind;
|
||||
|
||||
import org.apache.struts2.convention.annotation.Action;
|
||||
|
||||
//should never be found by the scanner
|
||||
public class DontFindMeAction {
|
||||
@Action("foo")
|
||||
public String foo() {
|
||||
return "bar";
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user