Adding the codebehind plugin, which minimizes the amount of configuration needed for common cases (default results and templates with no Action)

WW-1515


git-svn-id: https://svn.apache.org/repos/asf/struts/struts2/trunk@476709 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Donald J. Brown
2006-11-19 05:03:10 +00:00
parent ddbff80121
commit 2922e3c31e
5 changed files with 380 additions and 0 deletions
+65
View File
@@ -0,0 +1,65 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-plugins</artifactId>
<version>2.0.2-SNAPSHOT</version>
</parent>
<groupId>org.apache.struts</groupId>
<artifactId>struts2-codebehind-plugin</artifactId>
<packaging>jar</packaging>
<name>Struts 2 Codebehind Plugin</name>
<scm>
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/struts2/trunk/plugins/codebehind/</connection>
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/struts2/trunk/plugins/codebehind/</developerConnection>
<url>http://svn.apache.org/viewcvs.cgi/struts/struts2/trunk/plugins/codebehind/</url>
</scm>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
<version>3.8.1</version>
</dependency>
<dependency>
<groupId>mockobjects</groupId>
<artifactId>mockobjects-core</artifactId>
<version>0.09</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-mock</artifactId>
<version>1.2.8</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-core</artifactId>
<version>1.2.8</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>
@@ -0,0 +1,212 @@
/*
* $Id: DWRValidator.java 476642 2006-11-18 22:40:18Z mrdon $
*
* Licensed 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.codebehind;
import java.net.MalformedURLException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import javax.servlet.ServletContext;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
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.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.config.providers.InterceptorBuilder;
import com.opensymphony.xwork2.inject.Inject;
public class CodebehindUnknownHandler implements UnknownHandler {
protected String defaultPackageName = "codebehind-default";
protected ServletContext servletContext;
protected Map<String,ResultTypeConfig> resultsByExtension = new HashMap<String,ResultTypeConfig>();
protected String templatePathPrefix = "/";
protected Configuration configuration;
protected ObjectFactory objectFactory;
protected static final Log LOG = LogFactory.getLog(CodebehindUnknownHandler.class);
@Inject("struts.codebehind.defaultPackage")
public void setDefaultPackage(String pkg) {
this.defaultPackageName = pkg;
}
@Inject
public void setConfiguration(Configuration config) {
this.configuration = config;
}
@Inject
public void setServletContext(ServletContext servletContext) {
this.servletContext = servletContext;
}
@Inject
public void setObjectFactory(ObjectFactory objectFactory) {
this.objectFactory = objectFactory;
}
protected Map<String,ResultTypeConfig> loadResultTypes(Configuration config) {
Map<String,ResultTypeConfig> resultTypes = new LinkedHashMap<String,ResultTypeConfig>();
PackageConfig parentPackage = config.getPackageConfig(defaultPackageName);
Map<String,ResultTypeConfig> results = parentPackage.getAllResultTypeConfigs();
resultTypes.put("jsp", results.get("dispatcher"));
resultTypes.put("vm", results.get("velocity"));
resultTypes.put("ftl", results.get("freemarker"));
return resultTypes;
}
public ActionConfig handleUnknownAction(String namespace, String actionName)
throws XWorkException {
if (resultsByExtension == null) {
resultsByExtension = loadResultTypes(configuration);
}
String pathPrefix = determinePath(templatePathPrefix, namespace);
ActionConfig actionConfig = null;
for (String ext : resultsByExtension.keySet()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Trying to locate unknown action template with extension ."+ext+" in directory "+pathPrefix);
}
String path = string(pathPrefix, actionName, "." , ext);
try {
if (servletContext.getResource(path) != null) {
actionConfig = buildActionConfig(path, namespace, actionName, resultsByExtension.get(ext));
break;
}
} catch (MalformedURLException e) {
LOG.warn("Unable to parse template path: "+path+", skipping...");
}
}
return actionConfig;
}
protected ActionConfig buildActionConfig(String path, String namespace, String actionName, ResultTypeConfig resultTypeConfig) {
if (resultsByExtension == null) {
resultsByExtension = loadResultTypes(configuration);
}
Map<String,ResultConfig> results = new HashMap<String,ResultConfig>();
HashMap params = new HashMap();
if (resultTypeConfig.getParams() != null) {
params.putAll(resultTypeConfig.getParams());
}
params.put(resultTypeConfig.getDefaultResultParam(), path);
PackageConfig pkg = configuration.getPackageConfig(defaultPackageName);
List interceptors = InterceptorBuilder.constructInterceptorReference(pkg, pkg.getFullDefaultInterceptorRef(),
Collections.EMPTY_MAP, null, objectFactory);
ResultConfig config = new ResultConfig(Action.SUCCESS, resultTypeConfig.getClazz(), params);
results.put(Action.SUCCESS, config);
return new ActionConfig("execute", ActionSupport.class.getName(), defaultPackageName, new HashMap(), results, interceptors);
}
public Result handleUnknownResult(ActionContext actionContext, String actionName,
ActionConfig actionConfig, String resultCode) throws XWorkException {
Result result = null;
PackageConfig pkg = configuration.getPackageConfig(actionConfig.getPackageName());
String ns = pkg.getNamespace();
String pathPrefix = determinePath(templatePathPrefix, ns);
for (String ext : resultsByExtension.keySet()) {
if (LOG.isDebugEnabled()) {
LOG.debug("Trying to locate result with extension ."+ext+" in directory "+pathPrefix);
}
String path = string(pathPrefix, actionName, "-", resultCode, "." , ext);
try {
if (servletContext.getResource(path) != null) {
result = buildResult(path, resultCode, resultsByExtension.get(ext), actionContext);
break;
}
} catch (MalformedURLException e) {
LOG.warn("Unable to parse template path: "+path+", skipping...");
}
path = string(pathPrefix, actionName, "." , ext);
try {
if (servletContext.getResource(path) != null) {
result = buildResult(path, resultCode, resultsByExtension.get(ext), actionContext);
break;
}
} catch (MalformedURLException e) {
LOG.warn("Unable to parse template path: "+path+", skipping...");
}
}
return result;
}
protected Result buildResult(String path, String resultCode, ResultTypeConfig config, ActionContext invocationContext) {
String resultClass = config.getClazz();
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(resultCode, resultClass, params);
try {
return objectFactory.buildResult(resultConfig, invocationContext.getContextMap());
} catch (Exception e) {
throw new XWorkException("Unable to build codebehind result", e, resultConfig);
}
}
protected String string(String... parts) {
StringBuilder sb = new StringBuilder();
for (String part : parts) {
sb.append(part);
}
return sb.toString();
}
protected String determinePath(String prefix, String ns) {
if (ns == null || "/".equals(ns)) {
ns = "";
}
if (ns.length() > 0) {
if (ns.charAt(0) == '/') {
ns = ns.substring(1);
}
if (ns.charAt(ns.length() - 1) != '/') {
ns += "/";
}
}
return prefix + ns;
}
}
@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!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.codebehind.CodebehindUnknownHandler" />
<package name="codebehind-default" extends="struts-default">
</package>
</struts>
@@ -0,0 +1,90 @@
/*
* $Id: DWRValidator.java 476642 2006-11-18 22:40:18Z mrdon $
*
* Licensed 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.codebehind;
import java.util.HashMap;
import javax.servlet.ServletContext;
import org.apache.struts2.StrutsTestCase;
import org.apache.struts2.config.NullResult;
import org.apache.struts2.dispatcher.ServletDispatcherResult;
import com.mockobjects.dynamic.Mock;
import com.opensymphony.xwork2.ActionContext;
import com.opensymphony.xwork2.ActionInvocation;
import com.opensymphony.xwork2.ObjectFactory;
import com.opensymphony.xwork2.Result;
import com.opensymphony.xwork2.VoidResult;
import com.opensymphony.xwork2.config.entities.ResultTypeConfig;
public class CodebehindUnknownHandlerTest extends StrutsTestCase {
CodebehindUnknownHandler handler;
Mock mockServletContext;
public void setUp() throws Exception {
super.setUp();
mockServletContext = new Mock(ServletContext.class);
handler = new CodebehindUnknownHandler();
handler.setConfiguration(configuration);
handler.setObjectFactory(container.getInstance(ObjectFactory.class));
handler.setServletContext((ServletContext)mockServletContext.proxy());
}
public void testBuildResult() {
ActionContext ctx = new ActionContext(new HashMap());
ResultTypeConfig config = new ResultTypeConfig("null", SomeResult.class.getName(), "location");
Result result = handler.buildResult("/foo.jsp", "success", config, ctx);
assertNotNull(result);
assertTrue(result instanceof SomeResult);
assertEquals("/foo.jsp", ((SomeResult) result).location);
}
public void testString() {
assertEquals("foo.bar.jim", handler.string("foo", ".", "bar", ".", "jim"));
}
public void testDeterminePath() {
assertEquals("/", handler.determinePath("/", ""));
assertEquals("/", handler.determinePath("/", null));
assertEquals("/", handler.determinePath("/", "/"));
assertEquals("/foo/", handler.determinePath("/", "/foo"));
assertEquals("/foo/", handler.determinePath("/", "/foo/"));
assertEquals("/foo/", handler.determinePath("/", "foo"));
}
public static class SomeResult implements Result {
public String location;
public void setLocation(String loc) {
this.location = loc;
}
public void execute(ActionInvocation invocation) throws Exception {
}
}
}
+1
View File
@@ -19,6 +19,7 @@
</scm>
<modules>
<module>codebehind</module>
<module>config-browser</module>
<module>jasperreports</module>
<module>jfreechart</module>