Author: mrdon
Date: Sat Dec 30 21:02:02 2006
New Revision: 491386
URL: http://svn.apache.org/viewvc?view=rev&rev=491386
Log:
Initial version of scope plugin that mimics JBoss Seam-style of scoped bijection
Added:
struts/sandbox/trunk/struts2-scope-plugin/
struts/sandbox/trunk/struts2-scope-plugin/pom.xml
struts/sandbox/trunk/struts2-scope-plugin/src/
struts/sandbox/trunk/struts2-scope-plugin/src/main/
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/In.java
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/Out.java
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/ScopeInterceptor.java
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/ScopeType.java
struts/sandbox/trunk/struts2-scope-plugin/src/main/resources/
struts/sandbox/trunk/struts2-scope-plugin/src/main/resources/struts-plugin.xml
Added: struts/sandbox/trunk/struts2-scope-plugin/pom.xml
URL:
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-scope-plugin/pom.xml?view=auto&rev=491386
==============================================================================
--- struts/sandbox/trunk/struts2-scope-plugin/pom.xml (added)
+++ struts/sandbox/trunk/struts2-scope-plugin/pom.xml Sat Dec 30 21:02:02 2006
@@ -0,0 +1,29 @@
+<?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-scope-plugin</artifactId>
+ <packaging>jar</packaging>
+ <name>Struts 2 Scope Plugin</name>
+
+ <scm>
+
<connection>scm:svn:http://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-scope-plugin/</connection>
+
<developerConnection>scm:svn:https://svn.apache.org/repos/asf/struts/sandbox/trunk/struts2-scope-plugin/</developerConnection>
+
<url>http://svn.apache.org/viewcvs.cgi/struts/sandbox/trunk/struts2-scope-plugin/</url>
+ </scm>
+
+ <dependencies>
+ <dependency>
+ <groupId>junit</groupId>
+ <artifactId>junit</artifactId>
+ <scope>test</scope>
+ <version>3.8.1</version>
+ </dependency>
+ </dependencies>
+</project>
Added:
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/In.java
URL:
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/In.java?view=auto&rev=491386
==============================================================================
---
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/In.java
(added)
+++
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/In.java
Sat Dec 30 21:02:02 2006
@@ -0,0 +1,23 @@
+package org.apache.struts2.interceptor.scope;
+
+public @interface In {
+ /**
+ * Specifies that a component should be instantiated if the context
variable is null.
+ */
+ boolean create() default false;
+
+ /**
+ * Specifies that the injected value must not be null, by default.
+ */
+ boolean required() default true;
+
+ /**
+ * Explicitly specify the scope to search, instead of searching all scopes.
+ */
+ ScopeType scope() default ScopeType.UNSPECIFIED;
+
+ /**
+ * The context variable name. Defaults to the name of the annotated field
or getter method.
+ */
+ String value() default "";
+}
Added:
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/Out.java
URL:
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/Out.java?view=auto&rev=491386
==============================================================================
---
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/Out.java
(added)
+++
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/Out.java
Sat Dec 30 21:02:02 2006
@@ -0,0 +1,19 @@
+package org.apache.struts2.interceptor.scope;
+
+public @interface Out {
+
+ /**
+ * Specifies that the injected value must not be null, by default.
+ */
+ boolean required() default true;
+
+ /**
+ * Explicitly specify the scope to search, instead of searching all scopes.
+ */
+ ScopeType scope() default ScopeType.ACTION_CONTEXT;
+
+ /**
+ * The context variable name. Defaults to the name of the annotated field
or getter method.
+ */
+ String value() default "";
+}
Added:
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/ScopeInterceptor.java
URL:
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/ScopeInterceptor.java?view=auto&rev=491386
==============================================================================
---
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/ScopeInterceptor.java
(added)
+++
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/ScopeInterceptor.java
Sat Dec 30 21:02:02 2006
@@ -0,0 +1,277 @@
+/*
+ * $Id: CreateSessionInterceptor.java 471756 2006-11-06 15:01:43Z husted $
+ *
+ * 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.interceptor.scope;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Method;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import javax.servlet.http.HttpServletResponse;
+import javax.servlet.http.HttpSession;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts2.ServletActionContext;
+import org.apache.struts2.StrutsException;
+import org.apache.struts2.dispatcher.ServletActionRedirectResult;
+import org.apache.struts2.dispatcher.ServletRedirectResult;
+import org.apache.struts2.interceptor.CreateSessionInterceptor;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.interceptor.AbstractInterceptor;
+import com.opensymphony.xwork2.util.AnnotationUtils;
+
+/**
+ * <!-- START SNIPPET: description -->
+ *
+ * This interceptor creates the HttpSession.
+ * <p/>
+ * This is particular usefull when using the <@s.token> tag in
freemarker templates.
+ * The tag <b>do</b> require that a HttpSession is already created since
freemarker commits
+ * the response to the client immediately.
+ *
+ * <!-- END SNIPPET: description -->
+ *
+ * <p/> <u>Interceptor parameters:</u>
+ *
+ *
+ * <!-- START SNIPPET: extending -->
+ *
+ * <ul>
+ * <li>none</li>
+ * </ul>
+ *
+ * <!-- END SNIPPET: extending -->
+ *
+ *
+ * <!-- START SNIPPET: parameters -->
+ *
+ * <ul>
+ *
+ * <li>None</li>
+ *
+ * </ul>
+ *
+ * <!-- END SNIPPET: parameters -->
+ *
+ * <b>Example:</b>
+ *
+ * <pre>
+ * <!-- START SNIPPET: example -->
+ *
+ * <action name="someAction" class="com.examples.SomeAction">
+ * <interceptor-ref name="create-session"/>
+ * <interceptor-ref name="defaultStack"/>
+ * <result name="input">input_with_token_tag.ftl</result>
+ * </action>
+ *
+ * <!-- END SNIPPET: example -->
+ * </pre>
+ *
+ * @version $Date: 2006-11-06 07:01:43 -0800 (Mon, 06 Nov 2006) $ $Id:
CreateSessionInterceptor.java 471756 2006-11-06 15:01:43Z husted $
+ */
+public class ScopeInterceptor extends AbstractInterceptor {
+
+ private static final long serialVersionUID = -4590322556118858869L;
+
+ private static final Log LOG = LogFactory.getLog(ScopeInterceptor.class);
+ private static final Map<Class,CachedMethods> cachedMethods =
Collections.synchronizedMap(new HashMap<Class,CachedMethods>());
+
+ /* (non-Javadoc)
+ * @see
com.opensymphony.xwork2.interceptor.Interceptor#intercept(com.opensymphony.xwork2.ActionInvocation)
+ */
+ public String intercept(ActionInvocation invocation) throws Exception {
+ Object action = invocation.getAction();
+
+ ActionContext ctx = invocation.getInvocationContext();
+ Class cls = action.getClass();
+ boolean flashScopeUsed = false;
+ List<Method> inMethods = findAnnotationedMethods(cls, false);
+ for (Method m : inMethods) {
+ In in = m.getAnnotation(In.class);
+ String propName = in.value();
+ if (propName.length() == 0) {
+ propName = determinePropertyName(m.getName(), false);
+ }
+
+ flashScopeUsed |= in.scope() == ScopeType.FLASH;
+
+ Object obj = findObjectInScope(in.scope(), propName, ctx);
+
+ if (in.required() && obj == null) {
+ throw new StrutsException("Scope object "+propName+" cannot be
found in scope "+in.scope());
+ }
+ m.invoke(action, obj);
+ }
+
+ if (flashScopeUsed) {
+ ctx.getSession().remove(ScopeType.FLASH.toString());
+ }
+
+ String ret = invocation.invoke();
+
+ List<Method> outMethods = findAnnotationedMethods(cls, true);
+ for (Method m : outMethods) {
+ Out out = m.getAnnotation(Out.class);
+ String propName = out.value();
+ if (propName.length() == 0) {
+ propName = determinePropertyName(m.getName(), true);
+ }
+
+ Object obj = m.invoke(action);
+
+ putObjectInScope(out.scope(), propName, ctx, obj);
+ }
+ return ret;
+ }
+
+
+ /**
+ * @param in
+ * @param propName
+ * @param ctx
+ */
+ private Object findObjectInScope(ScopeType scopeType, String propName,
ActionContext ctx) {
+ Object obj = null;
+ if (obj == null && (scopeType == ScopeType.ACTION_CONTEXT ||scopeType
== ScopeType.UNSPECIFIED)) {
+ obj = ctx.get(propName);
+ }
+ if (obj == null && (scopeType == ScopeType.REQUEST || scopeType ==
ScopeType.UNSPECIFIED)) {
+ obj = ServletActionContext.getRequest().getAttribute(propName);
+ }
+ if (obj == null && (scopeType == ScopeType.FLASH || scopeType ==
ScopeType.UNSPECIFIED)) {
+ HttpSession session =
ServletActionContext.getRequest().getSession(false);
+ if (session != null) {
+ Map flash =
(Map)session.getAttribute(ScopeType.FLASH.toString());
+ if (flash != null) {
+ obj = flash.get(propName);
+ }
+ }
+ }
+ if (obj == null && (scopeType == ScopeType.SESSION || scopeType ==
ScopeType.UNSPECIFIED)) {
+ obj = ctx.getSession().get(propName);
+ }
+ if (obj == null && (scopeType == ScopeType.APPLICATION || scopeType ==
ScopeType.UNSPECIFIED)) {
+ obj = ctx.getApplication().get(propName);
+ }
+ return obj;
+ }
+
+ private void putObjectInScope(ScopeType scopeType, String propName,
ActionContext ctx, Object obj) {
+ HttpSession session = null;
+ switch (scopeType) {
+ case ACTION_CONTEXT : ctx.put(propName, obj);
+ break;
+ case REQUEST :
ServletActionContext.getRequest().setAttribute(propName, obj);
+ break;
+ case FLASH : session =
ServletActionContext.getRequest().getSession(true);
+ Map<String,Object> flash =
(Map<String,Object>) session.getAttribute(ScopeType.FLASH.toString());
+ if (flash == null) {
+ flash = new HashMap<String,Object>();
+ }
+ flash.put(propName, obj);
+
session.setAttribute(ScopeType.FLASH.toString(), flash);
+ break;
+ case SESSION : session =
ServletActionContext.getRequest().getSession(true);
+ session.setAttribute(propName, obj);
+ break;
+ case APPLICATION : ctx.getApplication().put(propName, obj);
+ break;
+ }
+ }
+
+
+ private List<Method> findAnnotationedMethods(Class cls, boolean out) {
+ CachedMethods cache = cachedMethods.get(cls);
+ if (cache == null) {
+ cache = new CachedMethods();
+ cachedMethods.put(cls, cache);
+ }
+ List<Method> methods = null;
+ if (out) {
+ methods = cache.getOutMethods();
+ if (methods == null) {
+ methods = AnnotationUtils.findAnnotatedMethods(cls, Out.class);
+ cache.setOutMethods(methods);
+ }
+ } else {
+ methods = cache.getInMethods();
+ if (methods == null) {
+ methods = AnnotationUtils.findAnnotatedMethods(cls, In.class);
+ cache.setInMethods(methods);
+ }
+ }
+ return methods;
+ }
+
+ private String determinePropertyName(String methodName, boolean out) {
+ String name = methodName;
+ if (!out && methodName.startsWith("set")) {
+ name = name.substring("set".length());
+ } else if (out) {
+ if (methodName.startsWith("get") || methodName.startsWith("has")) {
+ name = name.substring("get".length());
+ } else if (methodName.startsWith("is")) {
+ name = name.substring("is".length());
+ }
+ }
+ if (Character.isUpperCase(name.charAt(0))) {
+ if (name.length() == 1 || !Character.isUpperCase(name.charAt(1))) {
+ name = Character.toLowerCase(name.charAt(0)) +
name.substring(1);return name;
+ }
+ }
+ return name;
+ }
+
+ private static class CachedMethods {
+ private List<Method> inMethods;
+ private List<Method> outMethods;
+ /**
+ * @return the inMethods
+ */
+ public List<Method> getInMethods() {
+ return inMethods;
+ }
+ /**
+ * @param inMethods the inMethods to set
+ */
+ public void setInMethods(List<Method> inMethods) {
+ this.inMethods = inMethods;
+ }
+ /**
+ * @return the outMethods
+ */
+ public List<Method> getOutMethods() {
+ return outMethods;
+ }
+ /**
+ * @param outMethods the outMethods to set
+ */
+ public void setOutMethods(List<Method> outMethods) {
+ this.outMethods = outMethods;
+ }
+ }
+
+}
Added:
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/ScopeType.java
URL:
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/ScopeType.java?view=auto&rev=491386
==============================================================================
---
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/ScopeType.java
(added)
+++
struts/sandbox/trunk/struts2-scope-plugin/src/main/java/org/apache/struts2/interceptor/scope/ScopeType.java
Sat Dec 30 21:02:02 2006
@@ -0,0 +1,10 @@
+package org.apache.struts2.interceptor.scope;
+
+public enum ScopeType {
+ APPLICATION,
+ SESSION,
+ REQUEST,
+ ACTION_CONTEXT,
+ FLASH,
+ UNSPECIFIED
+}
\ No newline at end of file
Added:
struts/sandbox/trunk/struts2-scope-plugin/src/main/resources/struts-plugin.xml
URL:
http://svn.apache.org/viewvc/struts/sandbox/trunk/struts2-scope-plugin/src/main/resources/struts-plugin.xml?view=auto&rev=491386
==============================================================================
---
struts/sandbox/trunk/struts2-scope-plugin/src/main/resources/struts-plugin.xml
(added)
+++
struts/sandbox/trunk/struts2-scope-plugin/src/main/resources/struts-plugin.xml
Sat Dec 30 21:02:02 2006
@@ -0,0 +1,13 @@
+<?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>
+ <package name="scope-default">
+ <interceptors>
+ <interceptor name="bean-scope"
class="org.apache.struts2.interceptor.scope.ScopeInterceptor"/>
+ </interceptors>
+ </package>
+</struts>