You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@struts.apache.org by mr...@apache.org on 2006/11/05 10:21:43 UTC

svn commit: r471384 - in /struts/struts2/trunk: apps/showcase/src/main/java/org/apache/struts2/showcase/person/ apps/showcase/src/main/resources/ apps/showcase/src/main/resources/org/apache/struts2/showcase/person/ apps/showcase/src/main/webapp/WEB-INF...

Author: mrdon
Date: Sun Nov  5 01:21:42 2006
New Revision: 471384

URL: http://svn.apache.org/viewvc?view=rev&rev=471384
Log:
Adding a classloader scanning configuration provider that uses several
annotations to discover Actions, packages, and namespaces at runtime
WW-1491

Added:
    struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java
      - copied, changed from r471248, struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPerson.java
    struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java
      - copied, changed from r471248, struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeople.java
    struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java
    struts/struts2/trunk/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPersonAction-conversion.properties
      - copied unchanged from r471248, struts/struts2/trunk/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPerson-conversion.properties
    struts/struts2/trunk/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/ClasspathConfigurationProvider.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Namespace.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/NullResult.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/ParentPackage.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Result.java
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Results.java
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/ClasspathConfigurationProviderTest.java
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/CustomNamespaceAction.java
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/CustomParentPackageAction.java
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/OneResultAction.java
    struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/TwoResultAction.java
Removed:
    struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/CreatePerson-validation.xml
    struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/CreatePerson.java
    struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPerson-conversion.properties
    struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPerson.java
    struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeople.java
    struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/Person-validation.xml
    struts/struts2/trunk/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/CreatePerson-validation.xml
    struts/struts2/trunk/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/EditPerson-conversion.properties
Modified:
    struts/struts2/trunk/apps/showcase/src/main/resources/struts-person.xml
    struts/struts2/trunk/apps/showcase/src/main/resources/struts.properties
    struts/struts2/trunk/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
    struts/struts2/trunk/apps/showcase/src/main/webapp/person/editPeople.jsp
    struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java

Copied: struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java (from r471248, struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPerson.java)
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java?view=diff&rev=471384&p1=struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPerson.java&r1=471248&p2=struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java&r2=471384
==============================================================================
--- struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPerson.java (original)
+++ struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/EditPersonAction.java Sun Nov  5 01:21:42 2006
@@ -17,17 +17,26 @@
  */
 package org.apache.struts2.showcase.person;
 
-import com.opensymphony.xwork2.ActionSupport;
-
-import java.util.List;
-import java.util.Iterator;
 import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.struts2.config.Result;
+import org.apache.struts2.config.Results;
+import org.apache.struts2.dispatcher.ServletRedirectResult;
+
+import com.opensymphony.xwork2.ActionSupport;
 
 /**
  * <code>EditPerson</code>
  *
  */
-public class EditPerson extends ActionSupport {
+@Results({
+    @Result(value="editPeople.jsp"),
+    @Result(name="error",value="editPeople.jsp"),
+    @Result(name="list", value="listPeople.action", type=ServletRedirectResult.class)
+})
+public class EditPersonAction extends ActionSupport {
 
 	private static final long serialVersionUID = 7699491775215130850L;
 	
@@ -70,7 +79,7 @@
             personManager.getPeople().remove(p);
             personManager.getPeople().add(p);
         }
-        return SUCCESS;
+        return "list";
     }
 
 }

Copied: struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java (from r471248, struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeople.java)
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java?view=diff&rev=471384&p1=struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeople.java&r1=471248&p2=struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java&r2=471384
==============================================================================
--- struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeople.java (original)
+++ struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/ListPeopleAction.java Sun Nov  5 01:21:42 2006
@@ -17,14 +17,16 @@
  */
 package org.apache.struts2.showcase.person;
 
-import com.opensymphony.xwork2.ActionSupport;
-
-import java.util.List;
 import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.struts2.config.Result;
+import org.apache.struts2.views.freemarker.FreemarkerResult;
+
+import com.opensymphony.xwork2.ActionSupport;
 
-/**
- */
-public class ListPeople extends ActionSupport {
+@Result(value="listPeople.ftl", type=FreemarkerResult.class)
+public class ListPeopleAction extends ActionSupport {
 	
 	private static final long serialVersionUID = 3608017189783645371L;
 	

Added: struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java (added)
+++ struts/struts2/trunk/apps/showcase/src/main/java/org/apache/struts2/showcase/person/NewPersonAction.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,58 @@
+/*
+ * $Id: CreatePerson.java 420385 2006-07-10 00:57:05Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.showcase.person;
+
+import org.apache.struts2.config.ParentPackage;
+import org.apache.struts2.config.Result;
+import org.apache.struts2.config.Results;
+import org.apache.struts2.views.freemarker.FreemarkerResult;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ */
+@ParentPackage("person")
+@Results({
+    @Result(value="newPerson.ftl", type=FreemarkerResult.class),
+    @Result(name="input", value="newPerson.ftl", type=FreemarkerResult.class)
+})
+public class NewPersonAction extends ActionSupport {
+	
+	private static final long serialVersionUID = 200410824352645515L;
+	
+	PersonManager personManager;
+    Person person;
+
+    public void setPersonManager(PersonManager personManager) {
+        this.personManager = personManager;
+    }
+
+    public String execute() {
+        personManager.createPerson(person);
+
+        return SUCCESS;
+    }
+
+    public Person getPerson() {
+        return person;
+    }
+
+    public void setPerson(Person person) {
+        this.person = person;
+    }
+}

Added: struts/struts2/trunk/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml (added)
+++ struts/struts2/trunk/apps/showcase/src/main/resources/org/apache/struts2/showcase/person/NewPersonAction-validation.xml Sun Nov  5 01:21:42 2006
@@ -0,0 +1,8 @@
+<!DOCTYPE validators PUBLIC "-//OpenSymphony Group//XWork Validator 1.0//EN" "http://www.opensymphony.com/xwork/xwork-validator-1.0.dtd">
+<validators>
+    <field name="person">
+        <field-validator type="visitor">
+            <message></message>
+        </field-validator>
+    </field>
+</validators>

Modified: struts/struts2/trunk/apps/showcase/src/main/resources/struts-person.xml
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/apps/showcase/src/main/resources/struts-person.xml?view=diff&rev=471384&r1=471383&r2=471384
==============================================================================
--- struts/struts2/trunk/apps/showcase/src/main/resources/struts-person.xml (original)
+++ struts/struts2/trunk/apps/showcase/src/main/resources/struts-person.xml Sun Nov  5 01:21:42 2006
@@ -5,26 +5,7 @@
 <!-- START SNIPPET: xworkSample -->
 
 <struts>
-    <package name="person" extends="struts-default" namespace="/person">
-        <action name="listPeople" class="org.apache.struts2.showcase.person.ListPeople">
-            <interceptor-ref name="validationWorkflowStack"/>
-            <result type="freemarker">listPeople.ftl</result>
-        </action>
-
-        <action name="newPerson!*" class="org.apache.struts2.showcase.person.CreatePerson" method="{1}">
-            <result type="redirect">listPeople.action</result>
-            <result name="input" type="freemarker">newPerson.ftl</result>
-        </action>
-
-        <action name="editPerson" class="org.apache.struts2.showcase.person.EditPerson">
-            <result>editPeople.jsp</result>
-        </action>
-
-        <action name="doEditPerson" class="org.apache.struts2.showcase.person.EditPerson" method="save">
-            <result name="error">editPeople.jsp</result>
-            <result type="redirect">listPeople.action</result>
-        </action>
-    </package>
+    <package name="person" extends="struts-default" namespace="/person" />
 </struts>
 
 <!--  END SNIPPET: xworkSample -->

Modified: struts/struts2/trunk/apps/showcase/src/main/resources/struts.properties
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/apps/showcase/src/main/resources/struts.properties?view=diff&rev=471384&r1=471383&r2=471384
==============================================================================
--- struts/struts2/trunk/apps/showcase/src/main/resources/struts.properties (original)
+++ struts/struts2/trunk/apps/showcase/src/main/resources/struts.properties Sun Nov  5 01:21:42 2006
@@ -9,3 +9,5 @@
 struts.freemarker.manager.classname=customFreemarkerManager
 struts.serve.static=true
 struts.serve.static.browserCache=false
+
+struts.configuration.files=struts-default.xml,struts-plugin.xml,struts.xml,org.apache.struts2.showcase.person

Modified: struts/struts2/trunk/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp?view=diff&rev=471384&r1=471383&r2=471384
==============================================================================
--- struts/struts2/trunk/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp (original)
+++ struts/struts2/trunk/apps/showcase/src/main/webapp/WEB-INF/decorators/main.jsp Sun Nov  5 01:21:42 2006
@@ -11,7 +11,8 @@
     com.opensymphony.xwork2.ActionInvocation inv = com.opensymphony.xwork2.ActionContext.getContext().getActionInvocation();
     org.apache.struts2.dispatcher.mapper.ActionMapping mapping = org.apache.struts2.ServletActionContext.getActionMapping();
     if (inv != null) {
-        sourceUrl += "?config="+inv.getProxy().getConfig().getLocation().getURI()+":"+inv.getProxy().getConfig().getLocation().getLineNumber();
+        com.opensymphony.xwork2.util.location.Location loc = inv.getProxy().getConfig().getLocation();
+        sourceUrl += "?config="+(loc != null ? loc.getURI()+":"+loc.getLineNumber() : "");
         sourceUrl += "&className="+inv.getProxy().getConfig().getClassName();
         
         if (inv.getResult() != null && inv.getResult() instanceof org.apache.struts2.dispatcher.StrutsResultSupport) {

Modified: struts/struts2/trunk/apps/showcase/src/main/webapp/person/editPeople.jsp
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/apps/showcase/src/main/webapp/person/editPeople.jsp?view=diff&rev=471384&r1=471383&r2=471384
==============================================================================
--- struts/struts2/trunk/apps/showcase/src/main/webapp/person/editPeople.jsp (original)
+++ struts/struts2/trunk/apps/showcase/src/main/webapp/person/editPeople.jsp Sun Nov  5 01:21:42 2006
@@ -6,7 +6,7 @@
 </head>
 
 <body>
-<s:form action="doEditPerson" theme="simple" validate="false">
+<s:form action="editPerson" theme="simple" validate="false">
 
     <table>
         <tr>
@@ -29,7 +29,7 @@
         </s:iterator>
     </table>
 
-    <s:submit value="Save all persons"/>
+    <s:submit method="save" value="Save all persons"/>
 </s:form>
 
 <ul>

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/ClasspathConfigurationProvider.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/ClasspathConfigurationProvider.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/ClasspathConfigurationProvider.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/ClasspathConfigurationProvider.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,354 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config;
+
+import java.lang.annotation.Annotation;
+import java.lang.reflect.Modifier;
+import java.net.URL;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.struts2.StrutsConstants;
+
+import com.opensymphony.xwork2.ObjectFactory;
+import com.opensymphony.xwork2.VoidResult;
+import com.opensymphony.xwork2.config.Configuration;
+import com.opensymphony.xwork2.config.ConfigurationException;
+import com.opensymphony.xwork2.config.ConfigurationProvider;
+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.util.ClassLoaderUtil;
+import com.opensymphony.xwork2.util.ResolverUtil;
+import com.opensymphony.xwork2.util.TextUtils;
+
+/**
+ * Loads the configuration by scanning the classpath looking for classes that end in
+ * 'Action'.  
+ */
+public class ClasspathConfigurationProvider implements ConfigurationProvider {
+
+    private static final String DEFAULT_PAGE_PREFIX = "struts.configuration.classpath.defaultPagePrefix";
+    private static final String DEFAULT_PAGE_EXTENSION = "struts.configuration.classpath.defaultPageExtension";
+    private static final String DEFAULT_PARENT_PACKAGE = "struts.configuration.classpath.defaultParentPackage";
+    private static final String ACTION = "Action";
+    private String[] packages;
+    private String defaultParentPackage = "struts-default";
+    private String defaultPageExtension = ".jsp";
+    private String defaultPagePrefix = "";
+    private PageLocator pageLocator = new ClasspathPageLocator();
+    private boolean initialized = false;
+    
+    private Map<String,PackageConfig> loadedPackageConfigs = new HashMap<String,PackageConfig>(); 
+    
+    private static final Log LOG = LogFactory.getLog(ClasspathConfigurationProvider.class);
+    
+    private Configuration configuration;
+    
+    public ClasspathConfigurationProvider(String[] pkgs) {
+        this.packages = pkgs;
+        
+        if (Settings.isSet(DEFAULT_PARENT_PACKAGE)) {
+            defaultParentPackage = Settings.get(DEFAULT_PARENT_PACKAGE);
+        }
+        
+        if (Settings.isSet(DEFAULT_PAGE_EXTENSION)) {
+            defaultPageExtension = Settings.get(DEFAULT_PAGE_EXTENSION);
+        }
+        
+        if (Settings.isSet(DEFAULT_PAGE_PREFIX)) {
+            defaultPagePrefix = Settings.get(DEFAULT_PAGE_PREFIX);
+        }
+        
+    }
+    
+    public static interface PageLocator {
+        public URL locate(String path);
+    }
+    
+    public static class ClasspathPageLocator implements PageLocator {
+        public URL locate(String path) {
+            return ClassLoaderUtil.getResource(path, getClass());
+        }
+    }
+
+    /**
+     * @param defaultParentPackage the defaultParentPackage to set
+     */
+    public void setDefaultParentPackage(String defaultParentPackage) {
+        this.defaultParentPackage = defaultParentPackage;
+    }
+    
+    /**
+     * @param defaultPageExtension the defaultPageExtension to set
+     */
+    public void setDefaultPageExtension(String defaultPageExtension) {
+        this.defaultPageExtension = defaultPageExtension;
+    }
+
+    /**
+     * @param defaultPagePrefix the defaultPagePrefix to set
+     */
+    public void setDefaultPagePrefix(String defaultPagePrefix) {
+        this.defaultPagePrefix = defaultPagePrefix;
+    }
+    
+    public void setPageLocator(PageLocator locator) {
+        this.pageLocator = locator;
+    }
+
+    /**
+     * @param pkgs
+     */
+    protected void loadPackages(String[] pkgs) {
+        ResolverUtil<Class> resolver = new ResolverUtil<Class>();
+        resolver.findSuffix(ACTION, pkgs);
+        Set actionClasses = resolver.getClasses();
+        for (Object obj : actionClasses) {
+           Class cls = (Class) obj;
+           if (!Modifier.isAbstract(cls.getModifiers())) {
+               processActionClass(cls, pkgs);
+           }
+        }
+        
+        for (String key : loadedPackageConfigs.keySet()) {
+            configuration.addPackageConfig(key, loadedPackageConfigs.get(key));
+        }
+    }
+    
+    protected void processActionClass(Class cls, String[] pkgs) {
+        String name = cls.getName();
+        String actionPackage = cls.getPackage().getName();
+        String actionNamespace = null;
+        String actionName = null;
+        for (String pkg : pkgs) {
+            if (name.startsWith(pkg)) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Processing class "+name);
+                }
+                name = name.substring(pkg.length() + 1);
+                
+                actionNamespace = "";
+                actionName = name;
+                int pos = name.lastIndexOf('.');
+                if (pos > -1) {
+                    actionNamespace = "/" + name.substring(0, pos).replace('.','/');
+                    actionName = name.substring(pos+1);
+                }
+                break;
+            }
+        }
+        
+        PackageConfig pkgConfig = loadPackageConfig(actionNamespace, actionPackage, cls);
+        
+        Annotation annotation = cls.getAnnotation(ParentPackage.class);
+        if (annotation != null) {
+            String parent = ((ParentPackage)annotation).value();
+            PackageConfig parentPkg = configuration.getPackageConfig(parent);
+            if (parentPkg == null) {
+                throw new ConfigurationException("Unable to locate parent package "+parent, annotation);
+            }
+            pkgConfig.addParent(parentPkg);
+            
+            if (!TextUtils.stringSet(pkgConfig.getNamespace()) && TextUtils.stringSet(parentPkg.getNamespace())) {
+                pkgConfig.setNamespace(parentPkg.getNamespace());
+            }
+        }
+        
+        actionName = actionName.substring(0, actionName.length() - ACTION.length());
+        
+        if (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();
+        }
+        
+        ActionConfig actionConfig = new ActionConfig();
+        actionConfig.setClassName(cls.getName());
+        actionConfig.setPackageName(actionPackage);
+        
+        actionConfig.setResults(new ResultMap<String,ResultConfig>(cls, actionName, pkgConfig));
+        
+        pkgConfig.addActionConfig(actionName, actionConfig);
+    }
+
+    /**
+     * @param actionPackage
+     */
+    protected PackageConfig loadPackageConfig(String actionNamespace, String actionPackage, Class actionClass) {
+        PackageConfig parent = null;
+        
+        if (actionClass != null) {
+            Namespace ns = (Namespace) actionClass.getAnnotation(Namespace.class);
+            if (ns != null) {
+                parent = loadPackageConfig(actionNamespace, actionPackage, null);
+                actionNamespace = ns.value();
+                actionPackage = actionClass.getName();
+            }
+        }
+        
+        PackageConfig pkgConfig = loadedPackageConfigs.get(actionPackage);
+        if (pkgConfig == null) {
+            pkgConfig = new PackageConfig();
+            pkgConfig.setName(actionPackage);
+
+            if (parent == null) {
+                parent = configuration.getPackageConfig(defaultParentPackage);
+            }
+            
+            if (parent == null) {
+                throw new ConfigurationException("Unable to locate default parent package: " +
+                        defaultParentPackage);
+            }
+            pkgConfig.addParent(parent);
+            
+            pkgConfig.setNamespace(actionNamespace);
+            
+            loadedPackageConfigs.put(actionPackage, pkgConfig);
+        }
+        return pkgConfig;
+    }
+
+    public void destroy() {
+        
+    }
+
+    public void init(Configuration configuration) throws ConfigurationException {
+        this.configuration = configuration;
+        loadedPackageConfigs.clear();
+        loadPackages(packages);
+        initialized = true;
+    }
+
+    public boolean needsReload() {
+        return !initialized;
+    }
+    
+    /**
+     * Creates result configs from result annotations, and if a result isn't found,
+     * creates them on the fly.
+     */
+    class ResultMap<K,V> extends HashMap<K,V> {
+        private Class actionClass;
+        private String actionName;
+        private PackageConfig pkgConfig;
+
+        public ResultMap(Class actionClass, String actionName, PackageConfig pkgConfig) {
+            this.actionClass = actionClass;
+            this.actionName = actionName;
+            this.pkgConfig = pkgConfig;
+            
+            // check if any annotations are around
+            while (!actionClass.getName().equals(Object.class.getName())) {
+                //noinspection unchecked
+                Results results = (Results) actionClass.getAnnotation(Results.class);
+                if (results != null) {
+                    // first check here...
+                    for (int i = 0; i < results.value().length; i++) {
+                        Result result = results.value()[i];
+                        ResultConfig config = createResultConfig(result);
+                        put((K)config.getName(), (V)config);
+                    }
+                }
+
+                // what about a single Result annotation?
+                Result result = (Result) actionClass.getAnnotation(Result.class);
+                if (result != null) {
+                    ResultConfig config = createResultConfig(result);
+                    put((K)config.getName(), (V)config);
+                }
+
+                actionClass = actionClass.getSuperclass();
+            }
+            
+        }
+        
+        protected ResultConfig createResultConfig(Result result) {
+            Class cls = result.type();
+            if (cls == NullResult.class) {
+                cls = null;
+            }
+            return createResultConfig(result.name(), cls, result.value());
+        }
+
+        public V get(Object key) {
+            
+            Object result = super.get(key);
+            if (result != null) {
+                return (V) result;
+            } else {
+                
+                // TODO: This code never is actually used, do to how the runtime configuration
+                // is created.
+                String actionPath = pkgConfig.getNamespace() + "/" + actionName;
+                
+                String fileName = actionPath + "-" + key + defaultPageExtension;
+                if (pageLocator.locate(defaultPagePrefix + fileName) == null) {
+                    fileName = actionPath + defaultPageExtension;
+                }
+
+                String location = defaultPagePrefix + fileName;
+                return (V) createResultConfig(key, null, location);
+            }
+        }
+
+        /**
+         * @param key
+         * @param resultClass
+         * @param location
+         * @return
+         */
+        private ResultConfig createResultConfig(Object key, Class resultClass, String location) {
+            Map configParams = null;
+            if (resultClass == null) {
+                String defaultResultType = pkgConfig.getFullDefaultResultType();
+                ResultTypeConfig resultType = (ResultTypeConfig) pkgConfig.getAllResultTypeConfigs().get(defaultResultType);
+                configParams = resultType.getParams();
+                String className = resultType.getClazz();
+                try {
+                    resultClass = ClassLoaderUtil.loadClass(className, getClass());
+                } catch (ClassNotFoundException ex) {
+                    throw new ConfigurationException("Unable to locate result class "+className, actionClass);
+                }
+            }
+   
+            String defaultParam;
+            try {
+                defaultParam = (String) resultClass.getField("DEFAULT_PARAM").get(null);
+            } catch (Exception e) {
+                // not sure why this happened, but let's just use a sensible choice
+                defaultParam = "location";
+            }
+   
+            HashMap params = new HashMap();
+            if (configParams != null) {
+                params.putAll(configParams);
+            }
+            params.put(defaultParam, location);
+            return new ResultConfig((String) key, resultClass.getName(), params);
+        }
+    }
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Namespace.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Namespace.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Namespace.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Namespace.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,29 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Allows an action class to specify its namespace
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Namespace {
+    String value();
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/NullResult.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/NullResult.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/NullResult.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/NullResult.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,33 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config;
+
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.Result;
+
+/**
+ * Null result to get around annotation defaults that can't be null
+ */
+public class NullResult implements Result {
+
+    public void execute(ActionInvocation invocation) throws Exception {
+        throw new IllegalStateException("Shouldn't be called");
+
+    }
+
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/ParentPackage.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/ParentPackage.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/ParentPackage.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/ParentPackage.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,29 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Allows an action class to specify an xwork package to inherit
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface ParentPackage {
+    String value();
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Result.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Result.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Result.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Result.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,33 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config;
+
+import com.opensymphony.xwork2.Action;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Defines an XWork Result
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Result {
+    String name() default Action.SUCCESS;
+    Class type() default NullResult.class;
+    String value();
+}

Added: struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Results.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Results.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Results.java (added)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/config/Results.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,29 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+/**
+ * Defines multiple XWork Results
+ */
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Results {
+    Result[] value();
+}

Modified: struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java?view=diff&rev=471384&r1=471383&r2=471384
==============================================================================
--- struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java (original)
+++ struts/struts2/trunk/core/src/main/java/org/apache/struts2/dispatcher/Dispatcher.java Sun Nov  5 01:21:42 2006
@@ -19,6 +19,8 @@
 
 import java.io.File;
 import java.io.IOException;
+import java.net.MalformedURLException;
+import java.net.URL;
 import java.util.ArrayList;
 import java.util.HashMap;
 import java.util.List;
@@ -35,8 +37,11 @@
 import org.apache.struts2.ServletActionContext;
 import org.apache.struts2.StrutsConstants;
 import org.apache.struts2.StrutsStatics;
+import org.apache.struts2.config.ClasspathConfigurationProvider;
 import org.apache.struts2.config.Settings;
 import org.apache.struts2.config.StrutsXmlConfigurationProvider;
+import org.apache.struts2.config.ClasspathConfigurationProvider.ClasspathPageLocator;
+import org.apache.struts2.config.ClasspathConfigurationProvider.PageLocator;
 import org.apache.struts2.dispatcher.mapper.ActionMapping;
 import org.apache.struts2.dispatcher.multipart.MultiPartRequest;
 import org.apache.struts2.dispatcher.multipart.MultiPartRequestWrapper;
@@ -175,7 +180,7 @@
      *
      * @param servletContext The servlet context
      */
-    private void init(ServletContext servletContext) {
+    private void init(final ServletContext servletContext) {
         boolean reloadi18n = Boolean.valueOf((String) Settings.get(StrutsConstants.STRUTS_I18N_RELOAD)).booleanValue();
         LocalizedTextUtil.setReloadBundles(reloadi18n);
 
@@ -258,14 +263,26 @@
             configFiles = Settings.get(StrutsConstants.STRUTS_CONFIGURATION_FILES);
         }
         if (configFiles != null) {
+            List<String> packages = new ArrayList<String>();
 	        String[] files = configFiles.split("\\s*[,]\\s*");
 	        for (String file : files) {
-	            if ("xwork.xml".equals(file)) {
-	                configurationManager.addConfigurationProvider(new XmlConfigurationProvider(file, false));
-	            } else {
-	                configurationManager.addConfigurationProvider(new StrutsXmlConfigurationProvider(file, false));
-	            }
+                if (file.endsWith(".xml")) {
+    	            if ("xwork.xml".equals(file)) {
+    	                configurationManager.addConfigurationProvider(new XmlConfigurationProvider(file, false));
+    	            } else {
+    	                configurationManager.addConfigurationProvider(new StrutsXmlConfigurationProvider(file, false));
+    	            }
+                } else {
+                    packages.add(file);
+                }
 	        }
+            
+            // Initialize the classloader scanner with the configured paths
+            if (packages.size() > 0) {
+                ClasspathConfigurationProvider provider = new ClasspathConfigurationProvider((String[])packages.toArray(new String[]{}));
+                provider.setPageLocator(new ServletContextPageLocator(servletContext));
+                configurationManager.addConfigurationProvider(provider);
+            }
         }
 
         synchronized(Dispatcher.class) {
@@ -622,6 +639,33 @@
      */
     public static void setPortletSupportActive(boolean portletSupportActive) {
         Dispatcher.portletSupportActive = portletSupportActive;
+    }
+
+    /**
+     * Resolves pages from the servlet context, failing over to the classpath
+     */
+    private final class ServletContextPageLocator implements PageLocator {
+        private final ServletContext context;
+        private ClasspathPageLocator classpathPageLocator = new ClasspathPageLocator();
+
+        private ServletContextPageLocator(ServletContext context) {
+            this.context = context;
+        }
+
+        public URL locate(String path) {
+            URL url = null;
+            try {
+                url = context.getResource(path);
+                if (url == null) {
+                    url = classpathPageLocator.locate(path);
+                }
+            } catch (MalformedURLException e) {
+                if (LOG.isDebugEnabled()) {
+                    LOG.debug("Unable to resolve path "+path+" against the servlet context");
+                }
+            }
+            return url;
+        }
     }
 
     /** Simple accessor for a static method */

Added: struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/ClasspathConfigurationProviderTest.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/ClasspathConfigurationProviderTest.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/ClasspathConfigurationProviderTest.java (added)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/ClasspathConfigurationProviderTest.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,98 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config;
+
+import java.util.Map;
+
+import org.apache.struts2.dispatcher.ServletDispatcherResult;
+
+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.impl.DefaultConfiguration;
+import com.opensymphony.xwork2.config.impl.MockConfiguration;
+
+import junit.framework.TestCase;
+
+public class ClasspathConfigurationProviderTest extends TestCase {
+
+    ClasspathConfigurationProvider provider;
+    Configuration config;
+    
+    public void setUp() {
+        provider = new ClasspathConfigurationProvider(new String[]{"org.apache.struts2.config"});
+        config = new DefaultConfiguration();
+        PackageConfig strutsDefault = new PackageConfig("struts-default");
+        strutsDefault.addResultTypeConfig(new ResultTypeConfig("dispatcher", ServletDispatcherResult.class.getName(), "location"));
+        strutsDefault.setDefaultResultType("dispatcher");
+        config.addPackageConfig("struts-default", strutsDefault);
+        PackageConfig customPackage = new PackageConfig("custom-package");
+        customPackage.setNamespace("/custom");
+        config.addPackageConfig("custom-package", customPackage);
+        provider.init(config);
+    }
+    
+    public void testFoundRootPackages() {
+        assertEquals(5, config.getPackageConfigs().size());
+        PackageConfig pkg = config.getPackageConfig("org.apache.struts2.config");
+        assertNotNull(pkg);
+        Map configs = pkg.getActionConfigs();
+        assertNotNull(configs);
+        assertEquals(1, configs.size());
+        assertNotNull(configs.get("customParentPackage"));
+    }
+    
+    public void testParentPackage() {
+        PackageConfig pkg = config.getPackageConfig("org.apache.struts2.config");
+        assertEquals(2, pkg.getParents().size());
+        Map configs = pkg.getActionConfigs();
+        ActionConfig config = (ActionConfig) configs.get("customParentPackage");
+        assertNotNull(config);
+        assertEquals("/custom", pkg.getNamespace());
+    }
+    
+    public void testCustomNamespace() {
+        PackageConfig pkg = config.getPackageConfig("org.apache.struts2.config.CustomNamespaceAction");
+        Map configs = pkg.getAllActionConfigs();
+        assertEquals(2, configs.size());
+        ActionConfig config = (ActionConfig) configs.get("customNamespace");
+        assertNotNull(config);
+        assertEquals("/mynamespace", pkg.getNamespace());
+        assertNotNull(configs.get("customParentPackage"));
+    }
+    
+    public void testResultAnnotations() {
+        PackageConfig pkg = config.getPackageConfig("org.apache.struts2.config.cltest");
+        assertEquals("/cltest", pkg.getNamespace());
+        ActionConfig acfg = pkg.getActionConfigs().get("twoResult");
+        assertNotNull(acfg);
+        assertEquals(3, acfg.getResults().size());
+    }
+    
+    public void testDynamicResults() {
+        PackageConfig pkg = config.getPackageConfig("org.apache.struts2.config.cltest");
+        ActionConfig config = pkg.getActionConfigs().get("twoResult");
+        ResultConfig result = config.getResults().get("foobar");
+        assertNotNull(result);
+        assertEquals("/cltest/twoResult.jsp", result.getParams().get("location"));
+        assertEquals(ServletDispatcherResult.class.getName(), result.getClassName());
+    }
+
+}

Added: struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/CustomNamespaceAction.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/CustomNamespaceAction.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/CustomNamespaceAction.java (added)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/CustomNamespaceAction.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,23 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config;
+
+@Namespace("/mynamespace")
+public class CustomNamespaceAction {
+
+}

Added: struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/CustomParentPackageAction.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/CustomParentPackageAction.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/CustomParentPackageAction.java (added)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/CustomParentPackageAction.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,23 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config;
+
+@ParentPackage("custom-package")
+public class CustomParentPackageAction {
+
+}

Added: struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/OneResultAction.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/OneResultAction.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/OneResultAction.java (added)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/OneResultAction.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,25 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config.cltest;
+
+import org.apache.struts2.config.Result;
+
+@Result("foo.jsp")
+public class OneResultAction {
+
+}

Added: struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/TwoResultAction.java
URL: http://svn.apache.org/viewvc/struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/TwoResultAction.java?view=auto&rev=471384
==============================================================================
--- struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/TwoResultAction.java (added)
+++ struts/struts2/trunk/core/src/test/java/org/apache/struts2/config/cltest/TwoResultAction.java Sun Nov  5 01:21:42 2006
@@ -0,0 +1,31 @@
+/*
+ * $Id: DefaultSettings.java 439747 2006-09-03 09:22:46Z mrdon $
+ *
+ * Copyright 2006 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.struts2.config.cltest;
+
+import org.apache.struts2.config.Result;
+import org.apache.struts2.config.Results;
+import org.apache.struts2.dispatcher.ServletDispatcherResult;
+
+
+@Results({
+    @Result(name="chain", value="bob", type=ServletDispatcherResult.class),
+    @Result(name="input", value="input.jsp")
+})
+public class TwoResultAction extends OneResultAction {
+
+}