struts-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From lukaszlen...@apache.org
Subject [54/57] struts git commit: Merges xwork packages into struts
Date Wed, 17 Jun 2015 21:09:54 GMT
http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterUnitTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterUnitTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterUnitTest.java
new file mode 100644
index 0000000..d1ea4ca
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationParameterFilterUnitTest.java
@@ -0,0 +1,173 @@
+package com.opensymphony.xwork2.interceptor.annotations;
+
+import com.mockobjects.dynamic.Mock;
+import com.opensymphony.xwork2.Action;
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionInvocation;
+import com.opensymphony.xwork2.StubValueStack;
+import com.opensymphony.xwork2.util.ValueStack;
+import junit.framework.TestCase;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author martin.gilday
+ * @author jafl
+ *
+ */
+public class AnnotationParameterFilterUnitTest extends TestCase {
+
+	ValueStack stack;
+
+	@Override
+	protected void setUp() throws Exception {
+		super.setUp();
+		stack = new StubValueStack();
+	}
+
+	/**
+	 * Only "name" should remain in the parameter map.  All others
+	 * should be removed
+	 * @throws Exception
+	 */
+	public void testBlockingByDefault() throws Exception {
+
+		Map<String, Object> contextMap = new HashMap<>();
+		Map<String, Object> parameterMap = new HashMap<>();
+		
+		parameterMap.put("job", "Baker");
+		parameterMap.put("name", "Martin");
+		
+		contextMap.put(ActionContext.PARAMETERS, parameterMap);
+		
+		Action action = new BlockingByDefaultAction();
+		stack.push(action);
+		
+		Mock mockInvocation = new Mock(ActionInvocation.class);
+		mockInvocation.expectAndReturn("getInvocationContext", new ActionContext(contextMap));
+		mockInvocation.matchAndReturn("getAction", action);
+		mockInvocation.matchAndReturn("getStack", stack);
+		mockInvocation.expectAndReturn("invoke", Action.SUCCESS);
+		
+		ActionInvocation invocation = (ActionInvocation) mockInvocation.proxy();
+		
+		AnnotationParameterFilterIntereptor intereptor = new AnnotationParameterFilterIntereptor();
+		intereptor.intercept(invocation);
+
+		assertEquals("Parameter map should contain one entry", 1, parameterMap.size());
+		assertNull(parameterMap.get("job"));
+		assertNotNull(parameterMap.get("name"));
+		
+	}
+
+	/**
+	 * "name" should be removed from the map, as it is blocked.
+	 * All other parameters should remain
+	 * @throws Exception
+	 */
+	public void testAllowingByDefault() throws Exception {
+
+		Map<String, Object> contextMap = new HashMap<>();
+		Map<String, Object> parameterMap = new HashMap<>();
+		
+		parameterMap.put("job", "Baker");
+		parameterMap.put("name", "Martin");
+		
+		contextMap.put(ActionContext.PARAMETERS, parameterMap);
+		
+		Action action = new AllowingByDefaultAction();
+		stack.push(action);
+		
+		Mock mockInvocation = new Mock(ActionInvocation.class);
+		mockInvocation.expectAndReturn("getInvocationContext", new ActionContext(contextMap));
+		mockInvocation.matchAndReturn("getAction", action);
+		mockInvocation.matchAndReturn("getStack", stack);
+		mockInvocation.expectAndReturn("invoke", Action.SUCCESS);
+		
+		ActionInvocation invocation = (ActionInvocation) mockInvocation.proxy();
+		
+		AnnotationParameterFilterIntereptor intereptor = new AnnotationParameterFilterIntereptor();
+		intereptor.intercept(invocation);
+		
+		assertEquals("Paramter map should contain one entry", 1, parameterMap.size());
+		assertNotNull(parameterMap.get("job"));
+		assertNull(parameterMap.get("name"));
+		
+	}
+
+	/**
+	 * Only "name" should remain in the parameter map.  All others
+	 * should be removed
+	 * @throws Exception
+	 */
+	public void testBlockingByDefaultWithModel() throws Exception {
+
+		Map<String, Object> contextMap = new HashMap<>();
+		Map<String, Object> parameterMap = new HashMap<>();
+		
+		parameterMap.put("job", "Baker");
+		parameterMap.put("name", "Martin");
+		parameterMap.put("m1", "s1");
+		parameterMap.put("m2", "s2");
+		
+		contextMap.put(ActionContext.PARAMETERS, parameterMap);
+		stack.push(new BlockingByDefaultModel());
+		
+		Mock mockInvocation = new Mock(ActionInvocation.class);
+		mockInvocation.expectAndReturn("getInvocationContext", new ActionContext(contextMap));
+		mockInvocation.matchAndReturn("getAction", new BlockingByDefaultAction());
+		mockInvocation.matchAndReturn("getStack", stack);
+		mockInvocation.expectAndReturn("invoke", Action.SUCCESS);
+		
+		ActionInvocation invocation = (ActionInvocation) mockInvocation.proxy();
+		
+		AnnotationParameterFilterIntereptor intereptor = new AnnotationParameterFilterIntereptor();
+		intereptor.intercept(invocation);
+		
+		assertEquals("Paramter map should contain two entries", 2, parameterMap.size());
+		assertNull(parameterMap.get("job"));
+		assertNotNull(parameterMap.get("name"));
+		assertNotNull(parameterMap.get("m1"));
+		assertNull(parameterMap.get("m2"));
+		
+	}
+
+	/**
+	 * "name" should be removed from the map, as it is blocked.
+	 * All other parameters should remain
+	 * @throws Exception
+	 */
+	public void testAllowingByDefaultWithModel() throws Exception {
+
+		Map<String, Object> contextMap = new HashMap<>();
+		Map<String, Object> parameterMap = new HashMap<>();
+		
+		parameterMap.put("job", "Baker");
+		parameterMap.put("name", "Martin");
+		parameterMap.put("m1", "s1");
+		parameterMap.put("m2", "s2");
+		
+		contextMap.put(ActionContext.PARAMETERS, parameterMap);
+		stack.push(new AllowingByDefaultModel());
+		
+		Mock mockInvocation = new Mock(ActionInvocation.class);
+		mockInvocation.expectAndReturn("getInvocationContext", new ActionContext(contextMap));
+		mockInvocation.matchAndReturn("getAction", new AllowingByDefaultAction());
+		mockInvocation.matchAndReturn("getStack", stack);
+		mockInvocation.expectAndReturn("invoke", Action.SUCCESS);
+		
+		ActionInvocation invocation = (ActionInvocation) mockInvocation.proxy();
+		
+		AnnotationParameterFilterIntereptor intereptor = new AnnotationParameterFilterIntereptor();
+		intereptor.intercept(invocation);
+		
+		assertEquals("Paramter map should contain two entries", 2, parameterMap.size());
+		assertNotNull(parameterMap.get("job"));
+		assertNull(parameterMap.get("name"));
+		assertNull(parameterMap.get("m1"));
+		assertNotNull(parameterMap.get("m2"));
+		
+	}
+	
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationWorkflowInterceptorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationWorkflowInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationWorkflowInterceptorTest.java
new file mode 100644
index 0000000..e8b8d4f
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/AnnotationWorkflowInterceptorTest.java
@@ -0,0 +1,102 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.interceptor.annotations;
+
+import com.opensymphony.xwork2.*;
+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.InterceptorMapping;
+import com.opensymphony.xwork2.config.entities.PackageConfig;
+import com.opensymphony.xwork2.config.entities.ResultConfig;
+import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
+import com.opensymphony.xwork2.inject.ContainerBuilder;
+import com.opensymphony.xwork2.mock.MockResult;
+import com.opensymphony.xwork2.util.location.LocatableProperties;
+
+import java.util.Collections;
+
+/**
+ * @author Zsolt Szasz, zsolt at lorecraft dot com
+ * @author Rainer Hermanns
+ */
+public class AnnotationWorkflowInterceptorTest extends XWorkTestCase {
+    private static final String ANNOTATED_ACTION = "annotatedAction";
+    private static final String SHORTCIRCUITED_ACTION = "shortCircuitedAction";
+    private final AnnotationWorkflowInterceptor annotationWorkflow = new AnnotationWorkflowInterceptor();
+
+    @Override
+    public void setUp() throws Exception{
+        super.setUp();
+        XmlConfigurationProvider provider = new XmlConfigurationProvider("xwork-default.xml");
+        container.inject(provider);
+        loadConfigurationProviders(provider, new MockConfigurationProvider());
+    }
+
+    public void testInterceptsBeforeAndAfter() throws Exception {
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", ANNOTATED_ACTION, null);
+        assertEquals(Action.SUCCESS, proxy.execute());
+        AnnotatedAction action = (AnnotatedAction)proxy.getInvocation().getAction();
+        assertEquals("baseBefore-before-execute-beforeResult-after", action.log);
+    }
+
+    public void testInterceptsShortcircuitedAction() throws Exception {
+        ActionProxy proxy = actionProxyFactory.createActionProxy("", SHORTCIRCUITED_ACTION, null);
+        assertEquals("shortcircuit", proxy.execute());
+        ShortcircuitedAction action = (ShortcircuitedAction)proxy.getInvocation().getAction();
+        assertEquals("baseBefore-before", action.log);
+    }
+
+    private class MockConfigurationProvider implements ConfigurationProvider {
+        private Configuration config;
+
+        public void init(Configuration configuration) throws ConfigurationException {
+            this.config = configuration;
+        }
+
+        public boolean needsReload() {
+            return false;
+        }
+
+        public void destroy() { }
+
+
+        public void register(ContainerBuilder builder, LocatableProperties props) throws ConfigurationException {
+            if (!builder.contains(ObjectFactory.class)) {
+                builder.factory(ObjectFactory.class);
+            }
+            if (!builder.contains(ActionProxyFactory.class)) {
+                builder.factory(ActionProxyFactory.class, DefaultActionProxyFactory.class);
+            }
+        }
+
+        public void loadPackages() throws ConfigurationException {
+            PackageConfig packageConfig = new PackageConfig.Builder("default")
+                    .addActionConfig(ANNOTATED_ACTION, new ActionConfig.Builder("defaultPackage", ANNOTATED_ACTION, AnnotatedAction.class.getName())
+                            .addInterceptors(Collections.singletonList(new InterceptorMapping("annotationWorkflow", annotationWorkflow)))
+                            .addResultConfig(new ResultConfig.Builder("success", MockResult.class.getName()).build())
+                            .build())
+                    .addActionConfig(SHORTCIRCUITED_ACTION, new ActionConfig.Builder("defaultPackage", SHORTCIRCUITED_ACTION, ShortcircuitedAction.class.getName())
+                            .addInterceptors(Collections.singletonList(new InterceptorMapping("annotationWorkflow", annotationWorkflow)))
+                            .addResultConfig(new ResultConfig.Builder("shortcircuit", MockResult.class.getName()).build())
+                            .build())
+                    .build();
+            config.addPackageConfig("defaultPackage", packageConfig);
+            config.addPackageConfig("default", new PackageConfig.Builder(packageConfig).name("default").build());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BaseAnnotatedAction.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BaseAnnotatedAction.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BaseAnnotatedAction.java
new file mode 100644
index 0000000..ed088f1
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BaseAnnotatedAction.java
@@ -0,0 +1,32 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.interceptor.annotations;
+
+/**
+ * @author Zsolt Szasz, zsolt at lorecraft dot com
+ * @author Rainer Hermanns
+ */
+public class BaseAnnotatedAction {
+
+	protected String log = "";
+	
+	@Before
+	public String baseBefore() {
+		log = log + "baseBefore-";
+		return null;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BlockingByDefaultAction.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BlockingByDefaultAction.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BlockingByDefaultAction.java
new file mode 100644
index 0000000..509fb72
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BlockingByDefaultAction.java
@@ -0,0 +1,24 @@
+package com.opensymphony.xwork2.interceptor.annotations;
+
+import com.opensymphony.xwork2.ActionSupport;
+
+/**
+ * @author martin.gilday
+ *
+ */
+@BlockByDefault
+public class BlockingByDefaultAction extends ActionSupport {
+	
+	@Allowed
+	private String name;
+	private String job;
+	
+	public void setName(String name) {
+		this.name = name;
+	}
+	
+	public void setJob(String job) {
+		this.job = job;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BlockingByDefaultModel.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BlockingByDefaultModel.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BlockingByDefaultModel.java
new file mode 100644
index 0000000..f3b6fbe
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/BlockingByDefaultModel.java
@@ -0,0 +1,22 @@
+package com.opensymphony.xwork2.interceptor.annotations;
+
+/**
+ * @author jafl
+ *
+ */
+@BlockByDefault
+public class BlockingByDefaultModel {
+	
+	@Allowed
+	private String m1;
+	private String m2;
+	
+	public void setM1(String s) {
+		m1 = s;
+	}
+	
+	public void setM2(String s) {
+		m2 = s;
+	}
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/ShortcircuitedAction.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/ShortcircuitedAction.java b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/ShortcircuitedAction.java
new file mode 100644
index 0000000..bfbd48c
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/interceptor/annotations/ShortcircuitedAction.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.interceptor.annotations;
+
+import com.opensymphony.xwork2.Action;
+
+/**
+ * @author Zsolt Szasz, zsolt at lorecraft dot com
+ * @author Rainer Hermanns
+ */
+public class ShortcircuitedAction extends BaseAnnotatedAction {	
+	@Before(priority=5)
+	public String before() {
+		log = log + "before";
+		return "shortcircuit";
+	}
+	
+	public String execute() {
+		log = log + "-execute-";
+		return Action.SUCCESS;
+	}
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/ognl/accessor/XWorkListPropertyAccessorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/ognl/accessor/XWorkListPropertyAccessorTest.java b/core/src/test/java/com/opensymphony/xwork2/ognl/accessor/XWorkListPropertyAccessorTest.java
new file mode 100644
index 0000000..6942a1f
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/ognl/accessor/XWorkListPropertyAccessorTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (c) 2005 Opensymphony. All Rights Reserved.
+ */
+package com.opensymphony.xwork2.ognl.accessor;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.util.ListHolder;
+import com.opensymphony.xwork2.util.ValueStack;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * XWorkListPropertyAccessorTest
+ * <p/>
+ * Created : Nov 7, 2005 3:54:44 PM
+ *
+ * @author Jason Carreira <jcarreira@eplus.com>
+ */
+public class XWorkListPropertyAccessorTest extends XWorkTestCase {
+
+    public void testContains() {
+        ValueStack vs = ActionContext.getContext().getValueStack();
+        ListHolder listHolder = new ListHolder();
+        vs.push(listHolder);
+
+        vs.setValue("longs", new String[] {"1", "2", "3"});
+
+        assertNotNull(listHolder.getLongs());
+        assertEquals(3, listHolder.getLongs().size());
+        assertEquals(new Long(1), (Long) listHolder.getLongs().get(0));
+        assertEquals(new Long(2), (Long) listHolder.getLongs().get(1));
+        assertEquals(new Long(3), (Long) listHolder.getLongs().get(2));
+
+        assertTrue(((Boolean) vs.findValue("longs.contains(1)")).booleanValue());
+    }
+
+    public void testCanAccessListSizeProperty() {
+        ValueStack vs = ActionContext.getContext().getValueStack();
+        List myList = new ArrayList();
+        myList.add("a");
+        myList.add("b");
+
+        ListHolder listHolder = new ListHolder();
+        listHolder.setStrings(myList);
+
+        vs.push(listHolder);
+
+        assertEquals(new Integer(myList.size()), vs.findValue("strings.size()"));
+        assertEquals(new Integer(myList.size()), vs.findValue("strings.size"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/ActionAutowiringInterceptorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/ActionAutowiringInterceptorTest.java b/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/ActionAutowiringInterceptorTest.java
new file mode 100644
index 0000000..b399edf
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/ActionAutowiringInterceptorTest.java
@@ -0,0 +1,112 @@
+/*
+ * Created on 6/11/2004
+ */
+package com.opensymphony.xwork2.spring.interceptor;
+
+import com.opensymphony.xwork2.*;
+import com.opensymphony.xwork2.config.providers.XmlConfigurationProvider;
+import org.springframework.context.ApplicationContext;
+import org.springframework.web.context.WebApplicationContext;
+import org.springframework.web.context.support.StaticWebApplicationContext;
+
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * @author Simon Stewart
+ */
+public class ActionAutowiringInterceptorTest extends XWorkTestCase {
+
+    public void testShouldAutowireAction() throws Exception {
+        StaticWebApplicationContext context = new StaticWebApplicationContext();
+        context.getBeanFactory().registerSingleton("bean", new TestBean());
+        TestBean bean = (TestBean) context.getBean("bean");
+
+        loadSpringApplicationContextIntoApplication(context);
+
+        SimpleAction action = new SimpleAction();
+        ActionInvocation invocation = new TestActionInvocation(action);
+
+        ActionAutowiringInterceptor interceptor = new ActionAutowiringInterceptor();
+        interceptor.setApplicationContext(context);
+        interceptor.init();
+
+        interceptor.intercept(invocation);
+
+        assertEquals(bean, action.getBean());
+    }
+
+    public void testSetAutowireType() throws Exception {
+        XmlConfigurationProvider prov = new XmlConfigurationProvider("xwork-default.xml");
+        container.inject(prov);
+        prov.setThrowExceptionOnDuplicateBeans(false);
+        XmlConfigurationProvider c = new XmlConfigurationProvider("com/opensymphony/xwork2/spring/xwork-autowire.xml");
+        container.inject(c);
+        loadConfigurationProviders(c, prov);
+
+        StaticWebApplicationContext appContext = new StaticWebApplicationContext();
+
+        loadSpringApplicationContextIntoApplication(appContext);
+
+        ActionAutowiringInterceptor interceptor = new ActionAutowiringInterceptor();
+        interceptor.init();
+
+        SimpleAction action = new SimpleAction();
+        ActionInvocation invocation = new TestActionInvocation(action);
+
+        interceptor.intercept(invocation);
+
+        ApplicationContext loadedContext = interceptor.getApplicationContext();
+
+        assertEquals(appContext, loadedContext);
+    }
+
+    protected void loadSpringApplicationContextIntoApplication(ApplicationContext appContext) {
+        Map<Object, Object> application = new HashMap<>();
+        application.put(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, appContext);
+
+        Map<String, Object> context = new HashMap<>();
+        context.put(ActionContext.APPLICATION, application);
+        ActionContext actionContext = new ActionContext(context);
+        ActionContext.setContext(actionContext);
+    }
+
+    public void testLoadsApplicationContextUsingWebApplicationContextUtils() throws Exception {
+        StaticWebApplicationContext appContext = new StaticWebApplicationContext();
+
+        loadSpringApplicationContextIntoApplication(appContext);
+
+        ActionAutowiringInterceptor interceptor = new ActionAutowiringInterceptor();
+        interceptor.init();
+
+        SimpleAction action = new SimpleAction();
+        ActionInvocation invocation = new TestActionInvocation(action);
+
+        interceptor.intercept(invocation);
+
+        ApplicationContext loadedContext = interceptor.getApplicationContext();
+
+        assertEquals(appContext, loadedContext);
+    }
+
+    public void testIfApplicationContextIsNullThenBeanWillNotBeWiredUp() throws Exception {
+        Map<String, Object> context = new HashMap<>();
+        context.put(ActionContext.APPLICATION, new HashMap());
+        ActionContext actionContext = new ActionContext(context);
+        ActionContext.setContext(actionContext);
+
+        ActionAutowiringInterceptor interceptor = new ActionAutowiringInterceptor();
+        interceptor.init();
+
+        SimpleAction action = new SimpleAction();
+        ActionInvocation invocation = new TestActionInvocation(action);
+        TestBean bean = action.getBean();
+
+        // If an exception is thrown here, things are going to go wrong in
+        // production
+        interceptor.intercept(invocation);
+
+        assertEquals(bean, action.getBean());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/TestActionInvocation.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/TestActionInvocation.java b/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/TestActionInvocation.java
new file mode 100644
index 0000000..dd403b1
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/spring/interceptor/TestActionInvocation.java
@@ -0,0 +1,82 @@
+/*
+ * Created on 6/11/2004
+ */
+package com.opensymphony.xwork2.spring.interceptor;
+
+import com.opensymphony.xwork2.*;
+import com.opensymphony.xwork2.interceptor.PreResultListener;
+import com.opensymphony.xwork2.util.ValueStack;
+
+import java.lang.reflect.Method;
+
+/**
+ * @author Simon Stewart
+ */
+public class TestActionInvocation implements ActionInvocation {
+    private Object action;
+    private boolean executed;
+
+    public TestActionInvocation(Object wrappedAction) {
+        this.action = wrappedAction;
+    }
+
+    public Object getAction() {
+        return action;
+    }
+
+    public boolean isExecuted() {
+        return executed;
+    }
+
+    public ActionContext getInvocationContext() {
+        return null;
+    }
+
+    public ActionProxy getProxy() {
+        return null;
+    }
+
+    public Result getResult() throws Exception {
+        return null;
+    }
+
+    public String getResultCode() {
+        return null;
+    }
+
+    public void setResultCode(String resultCode) {
+
+    }
+
+    public ValueStack getStack() {
+        return null;
+    }
+
+    public void addPreResultListener(PreResultListener listener) {
+    }
+
+    public String invoke() throws Exception {
+        return invokeActionOnly();
+    }
+
+    public String invokeActionOnly() throws Exception {
+        executed = true;
+        Method method = action.getClass().getMethod("execute", new Class[0]);
+        return (String) method.invoke(action, new Object[0]);
+    }
+
+    public void setActionEventListener(ActionEventListener listener) {
+    }
+
+    public void init(ActionProxy proxy)  {
+    }
+
+    public ActionInvocation serialize() {
+        return this;
+    }
+
+    public ActionInvocation deserialize(ActionContext actionContext) {
+        return this;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/test/annotations/Address.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/test/annotations/Address.java b/core/src/test/java/com/opensymphony/xwork2/test/annotations/Address.java
new file mode 100644
index 0000000..8fe3bc8
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/test/annotations/Address.java
@@ -0,0 +1,40 @@
+package com.opensymphony.xwork2.test.annotations;
+
+public class Address {
+    private String line1;
+    private String line2;
+    private String city;
+    private String country;
+
+    public String getCity() {
+        return city;
+    }
+
+    public void setCity(String city) {
+        this.city = city;
+    }
+
+    public String getCountry() {
+        return country;
+    }
+
+    public void setCountry(String country) {
+        this.country = country;
+    }
+
+    public String getLine1() {
+        return line1;
+    }
+
+    public void setLine1(String line1) {
+        this.line1 = line1;
+    }
+
+    public String getLine2() {
+        return line2;
+    }
+
+    public void setLine2(String line2) {
+        this.line2 = line2;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/test/annotations/AddressTypeConverter.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/test/annotations/AddressTypeConverter.java b/core/src/test/java/com/opensymphony/xwork2/test/annotations/AddressTypeConverter.java
new file mode 100644
index 0000000..f0eadeb
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/test/annotations/AddressTypeConverter.java
@@ -0,0 +1,29 @@
+package com.opensymphony.xwork2.test.annotations;
+
+import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
+
+import java.util.Map;
+
+public class AddressTypeConverter extends DefaultTypeConverter {
+	@Override public Object convertValue(Map<String, Object> context, Object value, Class toType) {
+		if(value instanceof String) {
+			return decodeAddress((String)value);
+		} else if(value instanceof String && value.getClass().isArray()) {
+			return decodeAddress(((String[])value)[0]);
+		} else {
+			Address address = (Address)value;
+			return address.getLine1() + ":" + address.getLine2() + ":" +
+			       address.getCity() + ":" + address.getCountry();
+		}
+	}
+
+	private Address decodeAddress(String encodedAddress) {
+		String[] parts = ((String)encodedAddress).split(":");
+		Address address = new Address();
+		address.setLine1(parts[0]);
+		address.setLine2(parts[1]);
+		address.setCity(parts[2]);
+		address.setCountry(parts[3]);
+		return address;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/test/annotations/Person.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/test/annotations/Person.java b/core/src/test/java/com/opensymphony/xwork2/test/annotations/Person.java
new file mode 100644
index 0000000..4c47ee8
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/test/annotations/Person.java
@@ -0,0 +1,22 @@
+package com.opensymphony.xwork2.test.annotations;
+
+public class Person {
+	private String firstName;
+	private String lastName;
+	
+	public String getFirstName() {
+		return firstName;
+	}
+	
+	public void setFirstName(String firstName) {
+		this.firstName = firstName;
+	}
+	
+	public String getLastName() {
+		return lastName;
+	}
+	
+	public void setLastName(String lastName) {
+		this.lastName = lastName;
+	}
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonAction.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonAction.java b/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonAction.java
new file mode 100644
index 0000000..72e20ef
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonAction.java
@@ -0,0 +1,47 @@
+package com.opensymphony.xwork2.test.annotations;
+
+import com.opensymphony.xwork2.conversion.annotations.Conversion;
+import com.opensymphony.xwork2.conversion.annotations.ConversionType;
+import com.opensymphony.xwork2.conversion.annotations.TypeConversion;
+import com.opensymphony.xwork2.util.Element;
+
+import java.util.List;
+
+@Conversion(
+	conversions={
+		@TypeConversion(type=ConversionType.APPLICATION,
+						key="com.opensymphony.xwork2.test.annotations.Address",
+						converter="com.opensymphony.xwork2.test.annotations.AddressTypeConverter"),
+		@TypeConversion(type=ConversionType.APPLICATION,
+						key="com.opensymphony.xwork2.test.annotations.Person",
+						converter="com.opensymphony.xwork2.test.annotations.PersonTypeConverter")})
+public class PersonAction {
+	List<Person> users;
+	private List<Address> address;
+	@Element(com.opensymphony.xwork2.test.annotations.Address.class)
+	private List addressesNoGenericElementAnnotation;
+
+	public List<Person> getUsers() {
+		return users;
+	}
+
+	public void setUsers(List<Person> users) {
+		this.users = users;
+	}
+
+	public void setAddress(List<Address> address) {
+		this.address = address;
+	}
+
+	public List<Address> getAddress() {
+		return address;
+	}
+
+	public void setAddressesNoGenericElementAnnotation(List addressesNoGenericElementAnnotation) {
+		this.addressesNoGenericElementAnnotation = addressesNoGenericElementAnnotation;
+	}
+
+	public List getAddressesNoGenericElementAnnotation() {
+		return addressesNoGenericElementAnnotation;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonActionTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonActionTest.java b/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonActionTest.java
new file mode 100644
index 0000000..2f18b4d
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonActionTest.java
@@ -0,0 +1,87 @@
+package com.opensymphony.xwork2.test.annotations;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.conversion.impl.XWorkConverter;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.reflection.ReflectionContextState;
+
+import java.util.Map;
+
+
+public class PersonActionTest extends XWorkTestCase {
+    
+	public void testAddPerson() {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+
+        Map<String, Object> stackContext = stack.getContext();
+        stackContext.put(ReflectionContextState.CREATE_NULL_OBJECTS, Boolean.TRUE);
+        stackContext.put(ReflectionContextState.DENY_METHOD_EXECUTION, Boolean.TRUE);
+        stackContext.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
+
+        PersonAction action = new PersonAction();
+        stack.push(action);
+
+        stack.setValue("users", "jonathan:gerrish");
+        assertNotNull(action.getUsers());
+        assertEquals(1, action.getUsers().size());
+        
+        for(Object person : action.getUsers()) {
+        	System.out.println("Person: " + person);
+        }
+        
+        assertEquals(Person.class, action.getUsers().get(0).getClass());
+        assertEquals("jonathan", action.getUsers().get(0).getFirstName());
+        assertEquals("gerrish", action.getUsers().get(0).getLastName());
+	}
+	
+	public void testAddAddress() {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+		Map<String, Object> stackContext = stack.getContext();
+		stackContext.put(ReflectionContextState.CREATE_NULL_OBJECTS, Boolean.TRUE);
+		stackContext.put(ReflectionContextState.DENY_METHOD_EXECUTION, Boolean.TRUE);
+		stackContext.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
+
+		PersonAction action = new PersonAction();
+		stack.push(action);
+
+		stack.setValue("address", "2 Chandos Court:61 Haverstock Hill:London:England");
+		assertNotNull(action.getAddress());
+		assertEquals(1, action.getAddress().size());
+
+		for(Object address : action.getAddress()) {
+			System.out.println("Address: " + address);
+		}
+
+		assertEquals(Address.class, action.getAddress().get(0).getClass());
+		assertEquals("2 Chandos Court", action.getAddress().get(0).getLine1());
+		assertEquals("61 Haverstock Hill", action.getAddress().get(0).getLine2());
+		assertEquals("London", action.getAddress().get(0).getCity());
+		assertEquals("England", action.getAddress().get(0).getCountry());
+	}
+	
+	public void testAddAddressesNoGenericElementAnnotation() {
+        ValueStack stack = ActionContext.getContext().getValueStack();
+		Map<String, Object> stackContext = stack.getContext();
+		stackContext.put(ReflectionContextState.CREATE_NULL_OBJECTS, Boolean.TRUE);
+		stackContext.put(ReflectionContextState.DENY_METHOD_EXECUTION, Boolean.TRUE);
+		stackContext.put(XWorkConverter.REPORT_CONVERSION_ERRORS, Boolean.TRUE);
+
+		PersonAction action = new PersonAction();
+		stack.push(action);
+
+		stack.setValue("addressesNoGenericElementAnnotation", "2 Chandos Court:61 Haverstock Hill:London:England");
+		assertNotNull(action.getAddressesNoGenericElementAnnotation());
+		assertEquals(1, action.getAddressesNoGenericElementAnnotation().size());
+
+		for(Object address : action.getAddressesNoGenericElementAnnotation()) {
+			System.out.println("Address: " + address);
+		}
+
+		assertEquals(Address.class, action.getAddressesNoGenericElementAnnotation().get(0).getClass());
+		assertEquals("2 Chandos Court", ((Address)action.getAddressesNoGenericElementAnnotation().get(0)).getLine1());
+		assertEquals("61 Haverstock Hill", ((Address)action.getAddressesNoGenericElementAnnotation().get(0)).getLine2());
+		assertEquals("London", ((Address)action.getAddressesNoGenericElementAnnotation().get(0)).getCity());
+		assertEquals("England", ((Address)action.getAddressesNoGenericElementAnnotation().get(0)).getCountry());
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonTypeConverter.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonTypeConverter.java b/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonTypeConverter.java
new file mode 100644
index 0000000..6e27615
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/test/annotations/PersonTypeConverter.java
@@ -0,0 +1,27 @@
+package com.opensymphony.xwork2.test.annotations;
+
+import com.opensymphony.xwork2.conversion.impl.DefaultTypeConverter;
+
+import java.util.Map;
+
+public class PersonTypeConverter extends DefaultTypeConverter {
+	@Override
+    public Object convertValue(Map<String, Object> context, Object value, Class toType) {
+		if(value instanceof String) {
+			return decodePerson((String)value);
+		} else if(value instanceof String && value.getClass().isArray()) {
+			return decodePerson(((String[])value)[0]);
+		} else {
+			Person person = (Person)value;
+			return person.getFirstName() + ":" + person.getLastName();
+		}
+	}
+
+	private Person decodePerson(String encodedPerson) {
+		String[] parts = ((String)encodedPerson).split(":");
+		Person person = new Person();
+		person.setFirstName(parts[0]);
+		person.setLastName(parts[1]);
+		return person;
+	}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/test/annotations/ValidateAnnotatedMethodOnlyAction.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/test/annotations/ValidateAnnotatedMethodOnlyAction.java b/core/src/test/java/com/opensymphony/xwork2/test/annotations/ValidateAnnotatedMethodOnlyAction.java
new file mode 100644
index 0000000..5e2bb2a
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/test/annotations/ValidateAnnotatedMethodOnlyAction.java
@@ -0,0 +1,55 @@
+package com.opensymphony.xwork2.test.annotations;
+
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.validator.annotations.ExpressionValidator;
+import com.opensymphony.xwork2.validator.annotations.Validation;
+
+/**
+ * <code>ValidateAnnotatedMethodOnlyAction</code>
+ *
+ * @author <a href="mailto:hermanns@aixcept.de">Rainer Hermanns</a>
+ * @version $Id$
+ */
+@Validation
+public class ValidateAnnotatedMethodOnlyAction extends ActionSupport {
+
+    String param1;
+    String param2;
+
+
+    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;
+    }
+
+    @ExpressionValidator(expression = "(param1 != null) || (param2 != null)",
+            message = "Need param1 or param2.")
+    public String annotatedMethod() {
+        try {
+            // do search
+        } catch (Exception e) {
+            return INPUT;
+        }
+        return SUCCESS;
+    }
+
+    public String notAnnotatedMethod() {
+        try {
+            // do different search
+        } catch (Exception e) {
+            return INPUT;
+        }
+        return SUCCESS;
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/test/subtest/NullModelDrivenAction.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/test/subtest/NullModelDrivenAction.java b/core/src/test/java/com/opensymphony/xwork2/test/subtest/NullModelDrivenAction.java
new file mode 100644
index 0000000..6836cb8
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/test/subtest/NullModelDrivenAction.java
@@ -0,0 +1,19 @@
+package com.opensymphony.xwork2.test.subtest;
+
+import com.opensymphony.xwork2.ModelDrivenAction;
+
+/**
+ * Extends ModelDrivenAction to return a null model.
+ *
+ * @author Mark Woon
+ */
+public class NullModelDrivenAction extends ModelDrivenAction {
+
+    /**
+     * @return the model to be pushed onto the ValueStack instead of the Action itself
+     */
+    @Override
+    public Object getModel() {
+        return null;
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/annotation/Dummy2Class.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/Dummy2Class.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/Dummy2Class.java
new file mode 100644
index 0000000..7211e44
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/Dummy2Class.java
@@ -0,0 +1,9 @@
+package com.opensymphony.xwork2.util.annotation;
+
+public class Dummy2Class {
+
+    @MyAnnotation("class-test")
+    public void methodWithAnnotation() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClass.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClass.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClass.java
new file mode 100644
index 0000000..22d6e07
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClass.java
@@ -0,0 +1,13 @@
+package com.opensymphony.xwork2.util.annotation;
+
+@MyAnnotation("class-test")
+public class DummyClass {
+
+    public DummyClass() {
+    }
+
+    @MyAnnotation("method-test")
+    public void methodWithAnnotation() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClassExt.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClassExt.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClassExt.java
new file mode 100644
index 0000000..cfeebdf
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/DummyClassExt.java
@@ -0,0 +1,9 @@
+package com.opensymphony.xwork2.util.annotation;
+
+public final class DummyClassExt extends DummyClass {
+
+    @MyAnnotation2
+    public void anotherAnnotatedMethod() {
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation.java
new file mode 100644
index 0000000..0e5dd37
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation.java
@@ -0,0 +1,11 @@
+package com.opensymphony.xwork2.util.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MyAnnotation {
+
+    String value();
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation2.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation2.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation2.java
new file mode 100644
index 0000000..e517649
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/MyAnnotation2.java
@@ -0,0 +1,8 @@
+package com.opensymphony.xwork2.util.annotation;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+
+@Retention(RetentionPolicy.RUNTIME)
+public @interface MyAnnotation2 {
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/annotation/package-info.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/annotation/package-info.java b/core/src/test/java/com/opensymphony/xwork2/util/annotation/package-info.java
new file mode 100644
index 0000000..0d140c5
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/annotation/package-info.java
@@ -0,0 +1,22 @@
+/*
+ * $Id: package-info.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.
+ */
+@MyAnnotation("package-test")
+package com.opensymphony.xwork2.util.annotation;

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/fs/DefaultFileManagerFactoryTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/fs/DefaultFileManagerFactoryTest.java b/core/src/test/java/com/opensymphony/xwork2/util/fs/DefaultFileManagerFactoryTest.java
new file mode 100644
index 0000000..0b149c6
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/fs/DefaultFileManagerFactoryTest.java
@@ -0,0 +1,135 @@
+package com.opensymphony.xwork2.util.fs;
+
+import com.opensymphony.xwork2.FileManager;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.inject.Container;
+import com.opensymphony.xwork2.inject.Scope;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
+public class DefaultFileManagerFactoryTest extends XWorkTestCase {
+
+    static FileManager fileManager;
+
+    public void testCreateDefaultFileManager() throws Exception {
+        // given
+        fileManager = null;
+        DefaultFileManagerFactory factory = new DefaultFileManagerFactory();
+        factory.setFileManager(new DefaultFileManager());
+        factory.setContainer(new DummyContainer());
+
+        // when
+        FileManager fm = factory.getFileManager();
+
+        // then
+        assertTrue(fm instanceof DefaultFileManager);
+    }
+
+    public void testCreateDummyFileManager() throws Exception {
+        // given
+        fileManager = new DummyFileManager();
+        DefaultFileManagerFactory factory = new DefaultFileManagerFactory();
+        factory.setFileManager(new DefaultFileManager());
+        factory.setContainer(new DummyContainer());
+
+        // when
+        FileManager fm = factory.getFileManager();
+
+        // then
+        assertTrue(fm instanceof DummyFileManager);
+    }
+
+    public void testFileManagerFactoryWithRealConfig() throws Exception {
+        // given
+        DefaultFileManagerFactory factory = new DefaultFileManagerFactory();
+        container.inject(factory);
+
+        // when
+        FileManager fm = factory.getFileManager();
+
+        // then
+        assertTrue(fm instanceof DefaultFileManager);
+    }
+}
+
+class DummyContainer implements Container {
+    public void inject(Object o) {
+    }
+
+    public <T> T inject(Class<T> implementation) {
+        return null;
+    }
+
+    public <T> T getInstance(Class<T> type, String name) {
+        if ("dummy".equals(name)) {
+            return (T) DefaultFileManagerFactoryTest.fileManager;
+        }
+        return null;
+    }
+
+    public <T> T getInstance(Class<T> type) {
+        return null;
+    }
+
+    public Set<String> getInstanceNames(Class<?> type) {
+        if (DefaultFileManagerFactoryTest.fileManager != null) {
+            return new HashSet<String>() {
+                {
+                    add("dummy");
+                }
+            };
+        }
+        return Collections.emptySet();
+    }
+
+    public void setScopeStrategy(Scope.Strategy scopeStrategy) {
+    }
+
+    public void removeScopeStrategy() {
+    }
+
+}
+
+class DummyFileManager implements FileManager {
+
+    public void setReloadingConfigs(boolean reloadingConfigs) {
+    }
+
+    public boolean fileNeedsReloading(String fileName) {
+        return false;
+    }
+
+    public boolean fileNeedsReloading(URL fileUrl) {
+        return false;
+    }
+
+    public InputStream loadFile(URL fileUrl) {
+        return null;
+    }
+
+    public void monitorFile(URL fileUrl) {
+    }
+
+    public URL normalizeToFileProtocol(URL url) {
+        return null;
+    }
+
+    public boolean support() {
+        return true;
+    }
+
+    public boolean internal() {
+        return true;
+    }
+
+    public Collection<? extends URL> getAllPhysicalUrls(URL url) throws IOException {
+        return null;
+    }
+}
+

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/location/LocationAttributesTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/location/LocationAttributesTest.java b/core/src/test/java/com/opensymphony/xwork2/util/location/LocationAttributesTest.java
new file mode 100644
index 0000000..416e16c
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/location/LocationAttributesTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2006,2009 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.util.location;
+
+import junit.framework.TestCase;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.xml.sax.Locator;
+import org.xml.sax.helpers.AttributesImpl;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+public class LocationAttributesTest extends TestCase {
+    
+    public LocationAttributesTest(String name) {
+        super(name);
+    }
+    
+    public void testAddLocationAttributes() throws Exception {
+        AttributesImpl attrs = new AttributesImpl();
+        LocationAttributes.addLocationAttributes(new Locator() {
+            public int getColumnNumber() { return 40; }
+            public int getLineNumber() { return 1; }
+            public String getSystemId() { return "path/to/file.xml"; }
+            public String getPublicId() { return "path/to/file.xml"; }
+        }, attrs);
+
+        assertTrue("path/to/file.xml".equals(attrs.getValue("loc:src")));
+        assertTrue("1".equals(attrs.getValue("loc:line")));
+        assertTrue("40".equals(attrs.getValue("loc:column")));
+    }
+ 
+    public void testRecursiveRemove() throws Exception {
+        Document doc = getDoc("xml-with-location.xml");
+
+        Element root = doc.getDocumentElement();
+        LocationAttributes.remove(root, true);
+
+        assertNull(root.getAttributeNode("loc:line"));
+        assertNull(root.getAttributeNode("loc:column"));
+        assertNull(root.getAttributeNode("loc:src"));
+
+        Element kid = (Element)doc.getElementsByTagName("bar").item(0);
+        assertNull(kid.getAttributeNode("loc:line"));
+        assertNull(kid.getAttributeNode("loc:column"));
+        assertNull(kid.getAttributeNode("loc:src"));
+    }    
+
+    public void testNonRecursiveRemove() throws Exception {
+        Document doc = getDoc("xml-with-location.xml");
+
+        Element root = doc.getDocumentElement();
+        LocationAttributes.remove(root, false);
+
+        assertNull(root.getAttributeNode("loc:line"));
+        assertNull(root.getAttributeNode("loc:column"));
+        assertNull(root.getAttributeNode("loc:src"));
+
+        Element kid = (Element)doc.getElementsByTagName("bar").item(0);
+        assertNotNull(kid.getAttributeNode("loc:line"));
+        assertNotNull(kid.getAttributeNode("loc:column"));
+        assertNotNull(kid.getAttributeNode("loc:src"));
+    }    
+
+    private Document getDoc(String path) throws Exception {
+        DocumentBuilderFactory factory = DocumentBuilderFactory.newInstance();
+        factory.setNamespaceAware(true);
+        DocumentBuilder builder = factory.newDocumentBuilder();
+        return builder.parse(LocationAttributesTest.class.getResourceAsStream(path));
+
+
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/location/LocationImplTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/location/LocationImplTest.java b/core/src/test/java/com/opensymphony/xwork2/util/location/LocationImplTest.java
new file mode 100644
index 0000000..54b4dd4
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/location/LocationImplTest.java
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.util.location;
+
+import com.opensymphony.xwork2.util.ClassLoaderUtil;
+import junit.framework.TestCase;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.net.URL;
+import java.util.List;
+
+public class LocationImplTest extends TestCase {
+    
+    public LocationImplTest(String name) {
+        super(name);
+    }
+    
+    static final String str = "path/to/file.xml:1:40";
+
+    public void testEquals() throws Exception {
+        Location loc1 = LocationUtils.parse(str);
+        Location loc2 = new LocationImpl(null, "path/to/file.xml", 1, 40);
+        
+        assertEquals("locations", loc1, loc2);
+        assertEquals("hashcode", loc1.hashCode(), loc2.hashCode());
+        assertEquals("string representation", loc1.toString(), loc2.toString());
+    }
+    
+    /**
+     * Test that Location.UNKNOWN is kept identical on deserialization
+     */
+    public void testSerializeUnknown() throws Exception {
+        ByteArrayOutputStream bos = new ByteArrayOutputStream();
+        ObjectOutputStream oos = new ObjectOutputStream(bos);
+        
+        oos.writeObject(Location.UNKNOWN);
+        oos.close();
+        bos.close();
+        
+        ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
+        ObjectInputStream ois = new ObjectInputStream(bis);
+        
+        Object obj = ois.readObject();
+        
+        assertSame("unknown location", Location.UNKNOWN, obj);
+    }
+    
+    public void testGetSnippet() throws Exception {
+        URL url = ClassLoaderUtil.getResource("com/opensymphony/xwork2/somefile.txt", getClass());
+        Location loc = new LocationImpl("foo", url.toString(), 3, 2);
+        
+        List snippet = loc.getSnippet(1);
+        assertNotNull(snippet);
+        assertTrue("Wrong length: "+snippet.size(), 3 == snippet.size());
+        
+        assertTrue("is".equals(snippet.get(0)));
+        assertTrue("a".equals(snippet.get(1)));
+        assertTrue("file".equals(snippet.get(2)));
+    }
+    
+    public void testGetSnippetNoPadding() throws Exception {
+        URL url = ClassLoaderUtil.getResource("com/opensymphony/xwork2/somefile.txt", getClass());
+        Location loc = new LocationImpl("foo", url.toString(), 3, 2);
+        
+        List snippet = loc.getSnippet(0);
+        assertNotNull(snippet);
+        assertTrue("Wrong length: "+snippet.size(), 1 == snippet.size());
+        
+        assertTrue("a".equals(snippet.get(0)));
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/location/LocationUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/location/LocationUtilsTest.java b/core/src/test/java/com/opensymphony/xwork2/util/location/LocationUtilsTest.java
new file mode 100644
index 0000000..6a1bcc9
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/location/LocationUtilsTest.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.util.location;
+
+import junit.framework.TestCase;
+
+public class LocationUtilsTest extends TestCase {
+    
+    public LocationUtilsTest(String name) {
+        super(name);
+    }
+    
+    static final String str = "path/to/file.xml:1:40";
+
+    public void testParse() throws Exception {
+        String str = "<map:generate> - path/to/file.xml:1:40";
+        Location loc = LocationUtils.parse(str);
+        
+        assertEquals("<map:generate>", loc.getDescription());
+        assertEquals("URI", "path/to/file.xml", loc.getURI());
+        assertEquals("line", 1, loc.getLineNumber());
+        assertEquals("column", 40, loc.getColumnNumber());
+        assertEquals("string representation", str, loc.toString());
+    }
+    
+    public void testGetLocation_location() throws Exception {
+    		Location loc = new LocationImpl("desc", "sysId", 10, 4);
+    		assertTrue("Location should be the same", 
+				loc == LocationUtils.getLocation(loc, null));
+    }
+    
+    public void testGetLocation_exception() throws Exception {
+    		Exception e = new Exception();
+    		Location loc = LocationUtils.getLocation(e, null);
+    		
+    		assertTrue("Wrong sysId: "+loc.getURI(),
+    				"com/opensymphony/xwork2/util/location/LocationUtilsTest.java"
+    				.equals(loc.getURI()));
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/logging/LoggerUtilsTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/logging/LoggerUtilsTest.java b/core/src/test/java/com/opensymphony/xwork2/util/logging/LoggerUtilsTest.java
new file mode 100644
index 0000000..bead369
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/logging/LoggerUtilsTest.java
@@ -0,0 +1,24 @@
+package com.opensymphony.xwork2.util.logging;
+
+
+import junit.framework.TestCase;
+
+public class LoggerUtilsTest extends TestCase {
+
+    public void testFormatMessage() {
+        assertEquals("foo", LoggerUtils.format("foo"));
+        assertEquals("foo #", LoggerUtils.format("foo #"));
+        assertEquals("#foo", LoggerUtils.format("#foo"));
+        assertEquals("foo #1", LoggerUtils.format("foo #1"));
+        assertEquals("foo bob", LoggerUtils.format("foo #0", "bob"));
+        assertEquals("foo bob joe", LoggerUtils.format("foo #0 #1", "bob", "joe"));
+        assertEquals("foo bob joe #8", LoggerUtils.format("foo #0 #1 #8", "bob", "joe"));
+        assertEquals("foo (bob/ally)", LoggerUtils.format("foo (#0/#1)", "bob", "ally"));
+        assertEquals("foo (bobally)", LoggerUtils.format("foo (#0#1)", "bob", "ally"));
+
+        assertEquals(null, LoggerUtils.format(null));
+        assertEquals("", LoggerUtils.format(""));
+        
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/profiling/ProfilingTimerBeanTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/profiling/ProfilingTimerBeanTest.java b/core/src/test/java/com/opensymphony/xwork2/util/profiling/ProfilingTimerBeanTest.java
new file mode 100644
index 0000000..9106565
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/profiling/ProfilingTimerBeanTest.java
@@ -0,0 +1,124 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.util.profiling;
+
+import junit.framework.TestCase;
+
+/**
+ * 
+ * @author tm_jee
+ * @version $Date$ $Id$
+ */
+public class ProfilingTimerBeanTest extends TestCase {
+	
+	public void testAddChild() throws Exception {
+		ProfilingTimerBean bean0 = new ProfilingTimerBean("bean0");
+		ProfilingTimerBean bean1 = new ProfilingTimerBean("bean1");
+		ProfilingTimerBean bean2 = new ProfilingTimerBean("bean2");
+		ProfilingTimerBean bean3 = new ProfilingTimerBean("bean3");
+		ProfilingTimerBean bean4 = new ProfilingTimerBean("bean4");
+		ProfilingTimerBean bean5 = new ProfilingTimerBean("bean5");
+		ProfilingTimerBean bean6 = new ProfilingTimerBean("bean6");
+		ProfilingTimerBean bean7 = new ProfilingTimerBean("bean7");
+		ProfilingTimerBean bean8 = new ProfilingTimerBean("bean8");
+		
+		/*  bean0
+		 *    + bean1
+		 *       + bean2
+		 *    + bean3
+		 *       + bean4
+		 *         + bean5
+		 *           + bean6
+		 *       +bean7
+		 *    + bean8
+		 */
+		
+		bean0.addChild(bean1);
+		bean0.addChild(bean3);
+		bean0.addChild(bean8);
+		
+		bean1.addChild(bean2);
+		
+		bean3.addChild(bean4);
+		bean3.addChild(bean7);
+		
+		bean4.addChild(bean5);
+		
+		bean5.addChild(bean6);
+		
+		
+		// bean0
+		assertNull(bean0.getParent());
+		assertEquals(bean0.children.size(), 3);
+		assertTrue(bean0.children.contains(bean1));
+		assertTrue(bean0.children.contains(bean3));
+		assertTrue(bean0.children.contains(bean8));
+		
+		// bean1
+		assertEquals(bean1.getParent(), bean0);
+		assertEquals(bean1.children.size(), 1);
+		assertTrue(bean1.children.contains(bean2));
+		
+		// bean2
+		assertEquals(bean2.getParent(), bean1);
+		assertEquals(bean2.children.size(), 0);
+		
+		// bean3
+		assertEquals(bean3.getParent(), bean0);
+		assertEquals(bean3.children.size(), 2);
+		assertTrue(bean3.children.contains(bean4));
+		assertTrue(bean3.children.contains(bean7));
+		
+		// bean4
+		assertEquals(bean4.getParent(), bean3);
+		assertEquals(bean4.children.size(), 1);
+		assertTrue(bean4.children.contains(bean5));
+		
+		// bean5
+		assertEquals(bean5.getParent(), bean4);
+		assertEquals(bean5.children.size(), 1);
+		assertTrue(bean5.children.contains(bean6));
+		
+		// bean6
+		assertEquals(bean6.getParent(), bean5);
+		assertEquals(bean6.children.size(), 0);
+		
+		// bean7
+		assertEquals(bean7.getParent(), bean3);
+		assertEquals(bean7.children.size(), 0);
+		
+		// bean8
+		assertEquals(bean8.getParent(), bean0);
+		assertEquals(bean8.children.size(), 0);
+	}
+	
+	public void testTime() throws Exception {
+		ProfilingTimerBean bean0 = new ProfilingTimerBean("bean0");
+		bean0.setStartTime();
+		Thread.sleep(1050);
+		bean0.setEndTime();
+		assertTrue(bean0.totalTime >= 1000);
+	}
+	
+	public void testPrint() throws Exception {
+		ProfilingTimerBean bean0 = new ProfilingTimerBean("bean0");
+		bean0.setStartTime();
+		Thread.sleep(1050);
+		bean0.setEndTime();
+		assertEquals(bean0.getPrintable(2000), "");
+		assertTrue(bean0.getPrintable(500).length() > 0);
+	}
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/util/profiling/UtilTimerStackTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/util/profiling/UtilTimerStackTest.java b/core/src/test/java/com/opensymphony/xwork2/util/profiling/UtilTimerStackTest.java
new file mode 100644
index 0000000..1520d7cb
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/util/profiling/UtilTimerStackTest.java
@@ -0,0 +1,133 @@
+/*
+ * Copyright 2002-2006,2009 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package com.opensymphony.xwork2.util.profiling;
+
+import junit.framework.TestCase;
+
+/**
+ * @author tmjee
+ * @version $Date$ $Id$
+ */
+public class UtilTimerStackTest extends TestCase {
+
+    protected String activateProp;
+    protected String minTimeProp;
+
+
+    public void testActivateInactivate() throws Exception {
+        UtilTimerStack.setActive(true);
+        assertTrue(UtilTimerStack.isActive());
+        UtilTimerStack.setActive(false);
+        assertFalse(UtilTimerStack.isActive());
+    }
+
+
+    public void testPushPop() throws Exception {
+        UtilTimerStack.push("p1");
+        Thread.sleep(1050);
+        ProfilingTimerBean bean = UtilTimerStack.current.get();
+        assertTrue(bean.startTime > 0);
+        UtilTimerStack.pop("p1");
+        assertTrue(bean.totalTime > 1000);
+    }
+
+
+    public void testProfileCallback() throws Exception {
+
+        MockProfilingBlock<String> block = new MockProfilingBlock<String>() {
+            @Override
+            public String performProfiling() throws Exception {
+                Thread.sleep(1050);
+                return "OK";
+            }
+        };
+        String result = UtilTimerStack.profile("p1", block);
+        assertEquals(result, "OK");
+        assertNotNull(block.getProfilingTimerBean());
+        assertTrue(block.getProfilingTimerBean().totalTime >= 1000);
+
+    }
+
+
+    public void testProfileCallbackThrowsException() throws Exception {
+        try {
+            UtilTimerStack.profile("p1",
+                    new UtilTimerStack.ProfilingBlock<String>() {
+                        public String doProfiling() throws Exception {
+                            throw new RuntimeException("test");
+                        }
+                    });
+            fail("exception should have been thrown");
+        }
+        catch (Exception e) {
+            assertTrue(true);
+        }
+    }
+
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        activateProp = System.getProperty(UtilTimerStack.ACTIVATE_PROPERTY);
+        minTimeProp = System.getProperty(UtilTimerStack.MIN_TIME);
+
+        System.setProperty(UtilTimerStack.ACTIVATE_PROPERTY, "true");
+        UtilTimerStack.setActive(true);
+        System.setProperty(UtilTimerStack.MIN_TIME, "0");
+    }
+
+
+    @Override
+    protected void tearDown() throws Exception {
+
+        if (activateProp != null) {
+            System.setProperty(UtilTimerStack.ACTIVATE_PROPERTY, activateProp);
+        } else {
+            System.clearProperty(UtilTimerStack.ACTIVATE_PROPERTY);
+        }
+        if (minTimeProp != null) {
+            System.setProperty(UtilTimerStack.MIN_TIME, minTimeProp);
+        } else {
+            System.clearProperty(UtilTimerStack.ACTIVATE_PROPERTY);
+        }
+
+
+        activateProp = null;
+        minTimeProp = null;
+
+        super.tearDown();
+    }
+
+
+    public abstract class MockProfilingBlock<T> implements UtilTimerStack.ProfilingBlock<T> {
+
+        private ProfilingTimerBean bean;
+
+        public T doProfiling() throws Exception {
+            bean = UtilTimerStack.current.get();
+            return performProfiling();
+        }
+
+        public ProfilingTimerBean getProfilingTimerBean() {
+            return bean;
+        }
+
+        public abstract T performProfiling() throws Exception;
+    }
+}
+
+

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/validator/validators/AppendingValidatorContextTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/validators/AppendingValidatorContextTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/validators/AppendingValidatorContextTest.java
new file mode 100644
index 0000000..8ce3fb8
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/validators/AppendingValidatorContextTest.java
@@ -0,0 +1,47 @@
+package com.opensymphony.xwork2.validator.validators;
+
+import java.util.List;
+import java.util.Map;
+
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.validator.DelegatingValidatorContext;
+import com.opensymphony.xwork2.validator.ValidatorContext;
+import com.opensymphony.xwork2.validator.VisitorValidatorTestAction;
+import com.opensymphony.xwork2.validator.validators.VisitorFieldValidator.AppendingValidatorContext;
+
+public class AppendingValidatorContextTest extends XWorkTestCase {
+
+    private static final String FIRST_NAME = "first";
+    private static final String SECOND_NAME = "second";
+    private static final String FIELD_NAME = "fieldName";
+    private static final String FULL_FIELD_NAME = FIRST_NAME + "." + SECOND_NAME + "." + FIELD_NAME;
+
+    private VisitorValidatorTestAction action;
+    private VisitorFieldValidator.AppendingValidatorContext validatorContext;
+
+    @Override
+    protected void setUp() throws Exception {
+        super.setUp();
+
+        action = new VisitorValidatorTestAction();
+        ValidatorContext vc1 = new DelegatingValidatorContext(action);
+
+        VisitorFieldValidator.AppendingValidatorContext vc2 = new AppendingValidatorContext(
+                vc1, "value", FIRST_NAME, "");
+        validatorContext = new AppendingValidatorContext(vc2, "value", SECOND_NAME, "");
+    }
+
+    public void testGetFullFieldName() throws Exception {
+        String fullFieldName = validatorContext.getFullFieldName(FIELD_NAME);
+        assertEquals(FULL_FIELD_NAME, fullFieldName);
+    }
+
+    public void testAddFieldError() throws Exception {
+        validatorContext.addFieldError(FIELD_NAME, "fieldError");
+        assertTrue(action.hasFieldErrors());
+
+        Map<String, List<String>> fieldErrors = action.getFieldErrors();
+        assertEquals(1, fieldErrors.size());
+        assertTrue(fieldErrors.containsKey(FULL_FIELD_NAME));
+    }
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidatorTest.java
new file mode 100644
index 0000000..9103169
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/validators/DateRangeFieldValidatorTest.java
@@ -0,0 +1,93 @@
+package com.opensymphony.xwork2.validator.validators;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+import com.opensymphony.xwork2.validator.GenericValidatorContext;
+import com.opensymphony.xwork2.validator.ValidatorContext;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.Locale;
+
+public class DateRangeFieldValidatorTest extends XWorkTestCase {
+
+    public void testPassValidation() throws Exception {
+        // given
+        ValidationAction action = prepareAction(createDate(2013, 6, 6));
+        ValidatorContext context = new GenericValidatorContext(action);
+        DateRangeFieldValidator validator = prepareValidator(action, context);
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 0);
+    }
+
+    public void testMinValidation() throws Exception {
+        // given
+        ValidationAction action = prepareAction(createDate(2012, Calendar.MARCH, 3));
+        ValidatorContext context = new GenericValidatorContext(action);
+        DateRangeFieldValidator validator = prepareValidator(action, context);
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 1);
+        assertEquals("Max is 12.12.13, min is 01.01.13 but value is 03.03.12", context.getFieldErrors().get("dateRange").get(0));
+    }
+
+    public void testMaxValidation() throws Exception {
+        // given
+        ValidationAction action = prepareAction(createDate(2014, Calendar.APRIL, 4));
+        ValidatorContext context = new GenericValidatorContext(action);
+        DateRangeFieldValidator validator = prepareValidator(action, context);
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 1);
+        assertEquals("Max is 12.12.13, min is 01.01.13 but value is 04.04.14", context.getFieldErrors().get("dateRange").get(0));
+    }
+
+    private ValidationAction prepareAction(Date range) {
+        ValidationAction action = new ValidationAction();
+        action.setDateMinValue(createDate(2013, Calendar.JANUARY, 1));
+        action.setDateMaxValue(createDate(2013, Calendar.DECEMBER, 12));
+        action.setDateRange(range);
+        return action;
+    }
+
+    private Date createDate(int year, int month, int day) {
+        Calendar cal = Calendar.getInstance();
+        cal.set(year, month, day);
+        return cal.getTime();
+    }
+
+    private DateRangeFieldValidator prepareValidator(ValidationAction action, ValidatorContext context) {
+        ValueStack valueStack = container.getInstance(ValueStackFactory.class).createValueStack();
+        valueStack.push(action);
+
+        DateRangeFieldValidator validator = new DateRangeFieldValidator();
+        validator.setValueStack(valueStack);
+
+        validator.setMaxExpression("${dateMaxValue}");
+        validator.setMinExpression("${dateMinValue}");
+        validator.setValidatorContext(context);
+        validator.setFieldName("dateRange");
+        validator.setDefaultMessage("Max is ${dateMaxValue}, min is ${dateMinValue} but value is ${dateRange}");
+
+        return validator;
+    }
+
+    @Override
+    public void setUp() throws Exception {
+        super.setUp();
+        ActionContext.getContext().setLocale(new Locale("DE"));
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/validator/validators/IntRangeFieldValidatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/validators/IntRangeFieldValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/validators/IntRangeFieldValidatorTest.java
new file mode 100644
index 0000000..680ea08
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/validators/IntRangeFieldValidatorTest.java
@@ -0,0 +1,76 @@
+package com.opensymphony.xwork2.validator.validators;
+
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+import com.opensymphony.xwork2.validator.GenericValidatorContext;
+import com.opensymphony.xwork2.validator.ValidatorContext;
+
+public class IntRangeFieldValidatorTest extends XWorkTestCase {
+
+    public void testPassValidation() throws Exception {
+        // given
+        ValidationAction action = prepareAction(100);
+        ValidatorContext context = new GenericValidatorContext(action);
+        IntRangeFieldValidator validator = prepareValidator(action, context);
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 0);
+    }
+
+    public void testMinValidation() throws Exception {
+        // given
+        ValidationAction action = prepareAction(98);
+        ValidatorContext context = new GenericValidatorContext(action);
+        IntRangeFieldValidator validator = prepareValidator(action, context);
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 1);
+        assertEquals("Max is 101, min is 99 but value is 98", context.getFieldErrors().get("intRange").get(0));
+    }
+
+    public void testMaxValidation() throws Exception {
+        // given
+        ValidationAction action = prepareAction(102);
+        ValidatorContext context = new GenericValidatorContext(action);
+        IntRangeFieldValidator validator = prepareValidator(action, context);
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 1);
+        assertEquals("Max is 101, min is 99 but value is 102", context.getFieldErrors().get("intRange").get(0));
+    }
+
+    private ValidationAction prepareAction(int intRange) {
+        ValidationAction action = new ValidationAction();
+        action.setIntMaxValue(101);
+        action.setIntMinValue(99);
+        action.setIntRange(intRange);
+        return action;
+    }
+
+    private IntRangeFieldValidator prepareValidator(ValidationAction action, ValidatorContext context) {
+        ValueStack valueStack = container.getInstance(ValueStackFactory.class).createValueStack();
+        valueStack.push(action);
+
+        IntRangeFieldValidator validator = new IntRangeFieldValidator();
+        validator.setValueStack(valueStack);
+
+        validator.setMaxExpression("${intMaxValue}");
+        validator.setMinExpression("${intMinValue}");
+        validator.setValidatorContext(context);
+        validator.setFieldName("intRange");
+        validator.setDefaultMessage("Max is ${intMaxValue}, min is ${intMinValue} but value is ${intRange}");
+
+        return validator;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/validator/validators/LongRangeFieldValidatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/validators/LongRangeFieldValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/validators/LongRangeFieldValidatorTest.java
new file mode 100644
index 0000000..e8187d7
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/validators/LongRangeFieldValidatorTest.java
@@ -0,0 +1,76 @@
+package com.opensymphony.xwork2.validator.validators;
+
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.util.ValueStackFactory;
+import com.opensymphony.xwork2.validator.GenericValidatorContext;
+import com.opensymphony.xwork2.validator.ValidatorContext;
+
+public class LongRangeFieldValidatorTest extends XWorkTestCase {
+
+    public void testPassValidation() throws Exception {
+        // given
+        ValidationAction action = prepareAction(100);
+        ValidatorContext context = new GenericValidatorContext(action);
+        LongRangeFieldValidator validator = prepareValidator(action, context);
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 0);
+    }
+
+    public void testMinValidation() throws Exception {
+        // given
+        ValidationAction action = prepareAction(98);
+        ValidatorContext context = new GenericValidatorContext(action);
+        LongRangeFieldValidator validator = prepareValidator(action, context);
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 1);
+        assertEquals("Max is 101, min is 99 but value is 98", context.getFieldErrors().get("longRange").get(0));
+    }
+
+    public void testMaxValidation() throws Exception {
+        // given
+        ValidationAction action = prepareAction(102);
+        ValidatorContext context = new GenericValidatorContext(action);
+        LongRangeFieldValidator validator = prepareValidator(action, context);
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 1);
+        assertEquals("Max is 101, min is 99 but value is 102", context.getFieldErrors().get("longRange").get(0));
+    }
+
+    private ValidationAction prepareAction(long longRange) {
+        ValidationAction action = new ValidationAction();
+        action.setLongMaxValue(101L);
+        action.setLongMinValue(99L);
+        action.setLongRange(longRange);
+        return action;
+    }
+
+    private LongRangeFieldValidator prepareValidator(ValidationAction action, ValidatorContext context) {
+        ValueStack valueStack = container.getInstance(ValueStackFactory.class).createValueStack();
+        valueStack.push(action);
+
+        LongRangeFieldValidator validator = new LongRangeFieldValidator();
+        validator.setValueStack(valueStack);
+
+        validator.setMaxExpression("${longMaxValue}");
+        validator.setMinExpression("${longMinValue}");
+        validator.setValidatorContext(context);
+        validator.setFieldName("longRange");
+        validator.setDefaultMessage("Max is ${longMaxValue}, min is ${longMinValue} but value is ${longRange}");
+
+        return validator;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/struts/blob/82cb1286/core/src/test/java/com/opensymphony/xwork2/validator/validators/RequiredStringValidatorTest.java
----------------------------------------------------------------------
diff --git a/core/src/test/java/com/opensymphony/xwork2/validator/validators/RequiredStringValidatorTest.java b/core/src/test/java/com/opensymphony/xwork2/validator/validators/RequiredStringValidatorTest.java
new file mode 100644
index 0000000..2e33a7f
--- /dev/null
+++ b/core/src/test/java/com/opensymphony/xwork2/validator/validators/RequiredStringValidatorTest.java
@@ -0,0 +1,79 @@
+package com.opensymphony.xwork2.validator.validators;
+
+import com.opensymphony.xwork2.ActionContext;
+import com.opensymphony.xwork2.ActionSupport;
+import com.opensymphony.xwork2.XWorkTestCase;
+import com.opensymphony.xwork2.util.ValueStack;
+import com.opensymphony.xwork2.validator.GenericValidatorContext;
+import com.opensymphony.xwork2.validator.ValidatorContext;
+
+public class RequiredStringValidatorTest extends XWorkTestCase {
+
+    public void testRequiredStringPass() throws Exception {
+        // given
+        ValueStack valueStack = ActionContext.getContext().getValueStack();
+
+        ValidationAction action = new ValidationAction();
+        action.setStringValue("a string");
+        valueStack.push(action);
+
+        ValidatorContext context = new GenericValidatorContext(action);
+        RequiredStringValidator validator = new RequiredStringValidator();
+        validator.setValidatorContext(context);
+        validator.setFieldName("stringValue");
+        validator.setValueStack(valueStack);
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 0);
+    }
+
+    public void testRequiredStringFails() throws Exception {
+        // given
+        ValueStack valueStack = ActionContext.getContext().getValueStack();
+
+        ValidationAction action = new ValidationAction();
+        valueStack.push(action);
+
+        ValidatorContext context = new GenericValidatorContext(action);
+        RequiredStringValidator validator = new RequiredStringValidator();
+        validator.setValidatorContext(context);
+        validator.setFieldName("stringValue");
+        validator.setValueStack(valueStack);
+        validator.setDefaultMessage("Field ${fieldName} is required");
+
+        // when
+        validator.validate(action);
+
+        // then
+        assertTrue(context.getFieldErrors().size() == 1);
+        assertEquals(context.getFieldErrors().get("stringValue").get(0), "Field stringValue is required");
+    }
+
+
+    public void testTrimAsExpression() throws Exception {
+        // given
+        ValueStack valueStack = ActionContext.getContext().getValueStack();
+
+        ActionSupport action = new ActionSupport() {
+            public boolean getTrimValue() {
+                return false;
+            }
+        };
+        valueStack.push(action);
+
+        RequiredStringValidator validator = new RequiredStringValidator();
+        validator.setValueStack(valueStack);
+
+        assertTrue(validator.isTrim());
+
+        // when
+        validator.setTrimExpression("${trimValue}");
+
+        // then
+        assertFalse(validator.isTrim());
+    }
+
+}


Mime
View raw message